Skip to content

Commit

Permalink
#46 Fix wizard step rendering issue and validation (#47)
Browse files Browse the repository at this point in the history
* #46 Fix wizard step rendering issue

* #46 Rework to promise based step validation

* #46 Fix comments

* #46 Fix comments
  • Loading branch information
wouter-adriaens authored Jul 12, 2023
1 parent 40ffc7a commit b23a39b
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 79 deletions.
51 changes: 22 additions & 29 deletions src/__tests__/OeWizard.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ describe('OeWizard', () => {
components: { OeWizard },
setup() {
const steps: IStep[] = [
{ name: 'Algemene gegevens', valid: true },
{ name: 'Mijn gegevens', valid: true },
{ name: 'Bijlagen', valid: true },
{ name: 'Overzicht', valid: true },
{ name: 'Algemene gegevens', validate: () => Promise.resolve(true) },
{ name: 'Mijn gegevens', validate: () => Promise.resolve(true) },
{ name: 'Bijlagen', validate: () => Promise.resolve(true) },
{ name: 'Overzicht', validate: () => Promise.resolve(true) },
];

return { steps };
},
template: `
<oe-wizard :steps="steps">
<template #default="{ step, currentStep, totalSteps }">
<h2>Stap {{ currentStep + 1 }} van {{ totalSteps }} - {{ step.name }}</h2>
<template #default="{ currentStep, totalSteps }">
<h2>Stap {{ currentStep + 1 }} van {{ totalSteps }}</h2>
</template>
</oe-wizard>
`,
Expand Down Expand Up @@ -133,16 +133,16 @@ describe('OeWizard', () => {
});

it('renders the activated step in the default slot', () => {
cy.dataCy('step-1-content').invoke('text').should('equal', 'Stap 1 van 4 - Algemene gegevens');
cy.dataCy('step-1-content').invoke('text').should('equal', 'Stap 1 van 4');
cy.dataCy('next-step-button').click();

cy.dataCy('step-2-content').invoke('text').should('equal', 'Stap 2 van 4 - Mijn gegevens');
cy.dataCy('step-2-content').invoke('text').should('equal', 'Stap 2 van 4');
cy.dataCy('next-step-button').click();

cy.dataCy('step-3-content').invoke('text').should('equal', 'Stap 3 van 4 - Bijlagen');
cy.dataCy('step-3-content').invoke('text').should('equal', 'Stap 3 van 4');
cy.dataCy('next-step-button').click();

cy.dataCy('step-4-content').invoke('text').should('equal', 'Stap 4 van 4 - Overzicht');
cy.dataCy('step-4-content').invoke('text').should('equal', 'Stap 4 van 4');
});
});
});
Expand All @@ -152,10 +152,10 @@ describe('OeWizard', () => {
components: { OeWizard },
setup() {
const steps: IStep[] = [
{ name: 'Algemene gegevens', valid: true },
{ name: 'Mijn gegevens', valid: true },
{ name: 'Bijlagen', valid: true },
{ name: 'Overzicht', valid: true },
{ name: 'Algemene gegevens', validate: () => Promise.resolve(true) },
{ name: 'Mijn gegevens', validate: () => Promise.resolve(true) },
{ name: 'Bijlagen', validate: () => Promise.resolve(true) },
{ name: 'Overzicht', validate: () => Promise.resolve(true) },
];

return { steps };
Expand All @@ -178,10 +178,10 @@ describe('OeWizard', () => {
components: { OeWizard },
setup() {
const steps: IStep[] = [
{ name: 'Algemene gegevens', valid: true },
{ name: 'Mijn gegevens', valid: false },
{ name: 'Bijlagen', valid: true },
{ name: 'Overzicht', valid: true },
{ name: 'Algemene gegevens', validate: () => Promise.resolve(true) },
{ name: 'Mijn gegevens', validate: () => Promise.resolve(false) },
{ name: 'Bijlagen', validate: () => Promise.resolve(true) },
{ name: 'Overzicht', validate: () => Promise.resolve(true) },
];

return { steps };
Expand All @@ -193,13 +193,6 @@ describe('OeWizard', () => {
cy.mount(TestComponent);
});

it('disables the next step button when the current step is invalid', () => {
cy.dataCy('next-step-button').click();
cy.get('.wizard__bar-item--current').invoke('text').should('equal', '2Mijn gegevens');

cy.dataCy('next-step-button').should('be.disabled');
});

it('does not navigate to a step when previous step is invalid using bar navigation', () => {
cy.dataCy('step-3').click();
cy.get('.wizard__bar-item--current').invoke('text').should('equal', '1Algemene gegevens');
Expand All @@ -217,10 +210,10 @@ describe('OeWizard', () => {
components: { OeWizard },
setup() {
const steps: IStep[] = [
{ name: 'Algemene gegevens', valid: true },
{ name: 'Mijn gegevens', valid: false },
{ name: 'Bijlagen', valid: true },
{ name: 'Overzicht', valid: true },
{ name: 'Algemene gegevens', validate: () => Promise.resolve(true) },
{ name: 'Mijn gegevens', validate: () => Promise.resolve(false) },
{ name: 'Bijlagen', validate: () => Promise.resolve(true) },
{ name: 'Overzicht', validate: () => Promise.resolve(true) },
];

return { steps };
Expand Down
39 changes: 14 additions & 25 deletions src/components/dumb/OeWizard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,8 @@
</a>
</div>

<div
v-for="(step, index) in steps"
v-show="currentStep === index"
:key="index"
class="wizard__content vl-u-spacer--medium"
:data-cy="`step-${index + 1}-content`"
>
<slot :step="step" :current-step="currentStep" :total-steps="totalSteps"></slot>
<div class="wizard__content vl-u-spacer--medium" :data-cy="`step-${currentStep + 1}-content`">
<slot :current-step="currentStep" :total-steps="totalSteps"></slot>
</div>

<div class="wizard__actions vl-u-flex vl-u-flex-align-center">
Expand All @@ -42,29 +36,23 @@
v-if="currentStep < totalSteps - 1"
class="wizard__navigation-button"
data-cy="next-step-button"
:mod-disabled="!steps[currentStep].valid"
@click="nextStep"
>
Volgende
<font-awesome-icon :icon="['fas', 'angles-right']" />
</vl-button>
<vl-button
v-else
class="wizard__navigation-button"
data-cy="submit-button"
:mod-disabled="!steps.every((s) => s.valid)"
@click="emit('submit')"
<vl-button v-else class="wizard__navigation-button" data-cy="submit-button" @click="emit('submit')"
>Verzend</vl-button
>
</div>
</div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { VlBadge, VlButton } from '@govflanders/vl-ui-design-system-vue3';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import { VlBadge, VlButton } from '@govflanders/vl-ui-design-system-vue3';
import type { IWizardProps } from '@models/wizard';
import { ref } from 'vue';
// Next line should be activated once VlUTooltip is properly exported
// For now, an import of { VlUiUtil } in the implementing app also makes the tooltip available
Expand All @@ -85,20 +73,21 @@ const previousStep = () => {
}
};
const nextStep = () => {
if (currentStep.value < totalSteps.value - 1) {
const nextStep = async () => {
if (currentStep.value < totalSteps.value - 1 && (await props.steps[currentStep.value].validate())) {
currentStep.value++;
}
};
const goToStep = (step: number) => {
if (props.allowBarNavigation && previousStepsAreValid(step)) {
currentStep.value = step;
}
const goToStep = async (step: number) => {
if (props.allowBarNavigation && (await previousStepsAreValid(step))) currentStep.value = step;
};
const previousStepsAreValid = (step: number) => {
return props.steps.slice(0, step).every((s) => s.valid);
const previousStepsAreValid = async (step: number) => {
const steps = props.steps.slice(0, step);
const validations = await Promise.all(steps.map((s) => s.validate()));
return validations.every((v) => v);
};
</script>

Expand Down
2 changes: 1 addition & 1 deletion src/models/wizard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ export interface IWizardProps {

export interface IStep {
name: string;
valid: boolean;
validate: () => Promise<boolean>;
}
48 changes: 24 additions & 24 deletions src/stories/dumb-components/wizard.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,18 @@ export const Default: Story = {
},
setup() {
const steps: IStep[] = [
{ name: 'Gegevens EPC', valid: true },
{ name: 'Mijn gegevens', valid: true },
{ name: 'Bijlagen', valid: true },
{ name: 'Overzicht', valid: true },
{ name: 'Gegevens EPC', validate: () => Promise.resolve(true) },
{ name: 'Mijn gegevens', validate: () => Promise.resolve(true) },
{ name: 'Bijlagen', validate: () => Promise.resolve(true) },
{ name: 'Overzicht', validate: () => Promise.resolve(true) },
];

return { steps };
},
template: `
<oe-wizard :steps="steps">
<template #default="{ step, currentStep, totalSteps }">
<h2>Stap {{ currentStep + 1 }} van {{ totalSteps }} - {{ step.name }}</h2>
<template #default="{ currentStep, totalSteps }">
<h2>Stap {{ currentStep + 1 }} van {{ totalSteps }}</h2>
</template>
</oe-wizard>
`,
Expand All @@ -86,18 +86,18 @@ export const BarNavigationAllowed: Story = {
},
setup() {
const steps: IStep[] = [
{ name: 'Gegevens EPC', valid: true },
{ name: 'Mijn gegevens', valid: true },
{ name: 'Bijlagen', valid: true },
{ name: 'Overzicht', valid: true },
{ name: 'Gegevens EPC', validate: () => Promise.resolve(true) },
{ name: 'Mijn gegevens', validate: () => Promise.resolve(true) },
{ name: 'Bijlagen', validate: () => Promise.resolve(true) },
{ name: 'Overzicht', validate: () => Promise.resolve(true) },
];

return { steps };
},
template: `
<oe-wizard :steps="steps" allow-bar-navigation>
<template #default="{ step, currentStep, totalSteps }">
<h2>Stap {{ currentStep + 1 }} van {{ totalSteps }} - {{ step.name }}</h2>
<template #default="{ currentStep, totalSteps }">
<h2>Stap {{ currentStep + 1 }} van {{ totalSteps }}</h2>
</template>
</oe-wizard>
`,
Expand All @@ -119,18 +119,18 @@ export const BlockedWhenStepInvalid: Story = {
},
setup() {
const steps: IStep[] = [
{ name: 'Gegevens EPC', valid: true },
{ name: 'Mijn gegevens', valid: true },
{ name: 'Bijlagen', valid: false },
{ name: 'Overzicht', valid: false },
{ name: 'Gegevens EPC', validate: () => Promise.resolve(true) },
{ name: 'Mijn gegevens', validate: () => Promise.resolve(true) },
{ name: 'Bijlagen', validate: () => Promise.resolve(false) },
{ name: 'Overzicht', validate: () => Promise.resolve(false) },
];

return { steps };
},
template: `
<oe-wizard :steps="steps" allow-bar-navigation>
<template #default="{ step, currentStep, totalSteps }">
<h2>Stap {{ currentStep + 1 }} van {{ totalSteps }} - {{ step.name }}</h2>
<template #default="{ currentStep, totalSteps }">
<h2>Stap {{ currentStep + 1 }} van {{ totalSteps }}</h2>
</template>
</oe-wizard>
`,
Expand All @@ -157,18 +157,18 @@ export const Mobile: Story = {
},
setup() {
const steps: IStep[] = [
{ name: 'Gegevens EPC', valid: true },
{ name: 'Mijn gegevens', valid: true },
{ name: 'Bijlagen', valid: true },
{ name: 'Overzicht', valid: true },
{ name: 'Gegevens EPC', validate: () => Promise.resolve(true) },
{ name: 'Mijn gegevens', validate: () => Promise.resolve(true) },
{ name: 'Bijlagen', validate: () => Promise.resolve(true) },
{ name: 'Overzicht', validate: () => Promise.resolve(true) },
];

return { steps };
},
template: `
<oe-wizard :steps="steps">
<template #default="{ step, currentStep, totalSteps }">
<h2>Stap {{ currentStep + 1 }} van {{ totalSteps }} - {{ step.name }}</h2>
<template #default="{ currentStep, totalSteps }">
<h2>Stap {{ currentStep + 1 }} van {{ totalSteps }}</h2>
</template>
</oe-wizard>
`,
Expand Down

0 comments on commit b23a39b

Please sign in to comment.