Commit db05741a authored by Diana Zubova's avatar Diana Zubova Committed by Brandon Labuschagne

Improve alerts for addons purchase

parent 9622e8d7
......@@ -7,7 +7,11 @@ import Step from 'ee/vue_shared/purchase_flow/components/step.vue';
import { GENERAL_ERROR_MESSAGE } from 'ee/vue_shared/purchase_flow/constants';
import createFlash from '~/flash';
import autofocusonshow from '~/vue_shared/directives/autofocusonshow';
import { I18N_DETAILS_STEP_TITLE, I18N_DETAILS_NEXT_STEP_BUTTON_TEXT } from '../../constants';
import {
I18N_DETAILS_STEP_TITLE,
I18N_DETAILS_NEXT_STEP_BUTTON_TEXT,
I18N_DETAILS_INVALID_QUANTITY_MESSAGE,
} from '../../constants';
export default {
name: 'AddonPurchaseDetails',
......@@ -49,7 +53,7 @@ export default {
computed: {
quantityModel: {
get() {
return this.quantity || 1;
return this.quantity || 0;
},
set(quantity) {
this.updateQuantity(quantity);
......@@ -63,7 +67,7 @@ export default {
},
},
methods: {
updateQuantity(quantity = 1) {
updateQuantity(quantity = 0) {
this.$apollo
.mutate({
mutation: updateState,
......@@ -79,6 +83,7 @@ export default {
i18n: {
stepTitle: I18N_DETAILS_STEP_TITLE,
nextStepButtonText: I18N_DETAILS_NEXT_STEP_BUTTON_TEXT,
invalidQuantityErrorMessage: I18N_DETAILS_INVALID_QUANTITY_MESSAGE,
},
stepId: STEPS[0].id,
};
......@@ -89,6 +94,7 @@ export default {
:step-id="$options.stepId"
:title="$options.i18n.stepTitle"
:is-valid="isValid"
:error-message="$options.i18n.invalidQuantityErrorMessage"
:next-step-button-text="$options.i18n.nextStepButtonText"
>
<template #body>
......@@ -98,7 +104,12 @@ export default {
<label class="gl-mt-3" for="quantity" data-testid="product-label">
{{ productLabel }}
</label>
<div class="gl-display-flex gl-flex-direction-row gl-align-items-center gl-mb-6">
<div
:class="[
{ 'gl-mb-6': isValid },
'gl-display-flex gl-flex-direction-row gl-align-items-center',
]"
>
<gl-form-input
ref="quantity"
v-model.number="quantityModel"
......
......@@ -65,6 +65,9 @@ export default {
quantityPresent() {
return this.subscription.quantity > 0;
},
quantity() {
return this.subscription.quantity || 0;
},
namespaceName() {
return this.selectedNamespace.name;
},
......@@ -104,7 +107,7 @@ export default {
:selected-plan-text="plan.name"
:selected-plan-price="selectedPlanPrice"
:total-amount="totalAmount"
:quantity="subscription.quantity"
:quantity="quantity"
:tax-rate="$options.taxRate"
:purchase-has-expiration="purchaseHasExpiration"
>
......@@ -128,7 +131,7 @@ export default {
:selected-plan-text="plan.name"
:selected-plan-price="selectedPlanPrice"
:total-amount="totalAmount"
:quantity="subscription.quantity"
:quantity="quantity"
:tax-rate="$options.taxRate"
:purchase-has-expiration="purchaseHasExpiration"
>
......
......@@ -42,6 +42,7 @@ export const I18N_STORAGE_TOOLTIP_NOTE = s__(
export const I18N_DETAILS_STEP_TITLE = s__('Checkout|Purchase details');
export const I18N_DETAILS_NEXT_STEP_BUTTON_TEXT = s__('Checkout|Continue to billing');
export const I18N_DETAILS_INVALID_QUANTITY_MESSAGE = s__('Checkout|Enter a number greater than 0');
export const I18N_DETAILS_FORMULA = s__('Checkout|x %{quantity} %{units} per pack =');
export const I18N_DETAILS_FORMULA_WITH_ALERT = s__('Checkout|x %{quantity} %{units} per pack');
......
......@@ -35,6 +35,11 @@ export default {
required: false,
default: '',
},
errorMessage: {
type: String,
required: false,
default: '',
},
},
data() {
return {
......@@ -113,11 +118,15 @@ export default {
<div :class="['card', snakeCasedStep]">
<div v-show="isActive" @keyup.enter="nextStep">
<slot name="body" :active="isActive"></slot>
<gl-form-group v-if="nextStepButtonText" class="gl-mt-3 gl-mb-0">
<gl-form-group
v-if="nextStepButtonText"
:invalid-feedback="errorMessage"
:state="isValid"
:class="[!isValid && errorMessage ? 'gl-mb-5' : 'gl-mb-0', 'gl-mt-3']"
/>
<gl-button variant="success" category="primary" :disabled="!isValid" @click="nextStep">
{{ nextStepButtonText }}
</gl-button>
</gl-form-group>
</div>
<step-summary v-if="isFinished" :is-editable="isEditable" :edit="edit">
<slot name="summary"></slot>
......
import { GlButton } from '@gitlab/ui';
import { GlButton, GlFormGroup } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import Step from 'ee/vue_shared/purchase_flow/components/step.vue';
......@@ -114,6 +114,16 @@ describe('Step', () => {
expect(wrapper.findComponent(StepSummary).exists()).toBe(false);
});
it('should pass correct props to form component', () => {
wrapper = createComponent({
propsData: { errorMessage: 'Input value is invalid!' },
});
expect(wrapper.findComponent(GlFormGroup).attributes('invalid-feedback')).toBe(
'Input value is invalid!',
);
});
});
describe('isEditable', () => {
......
......@@ -6682,6 +6682,9 @@ msgstr ""
msgid "Checkout|Edit"
msgstr ""
msgid "Checkout|Enter a number greater than 0"
msgstr ""
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment