Add guided wash flow to MyWashStart.vue with step-by-step instructions, brush details, and improved user navigation

This commit is contained in:
Jeppe Bundgaard
2025-12-17 15:19:57 +01:00
parent da45e23324
commit ce2c313f63
@@ -21,6 +21,7 @@ import WhiteBoxCard from "@/components/displays/boxes/WhiteBoxCard.vue";
import {getDepartmentsGuest} from "@/components/pagination/departmentTabs.vue";
import {computed, onMounted, onUnmounted, ref, watch} from "vue";
import ColorIndicator from "@/components/displays/buttons/ColorIndicator.vue";
const guestDepartments = ref([]);
@@ -210,6 +211,11 @@ const formattedElapsed = computed(() => {
const totalSeconds = Math.floor(timeSinceWashStart.value / 1000);
const minutes = Math.floor(totalSeconds / 60);
const seconds = totalSeconds % 60;
// If the elapsed time is negative, return 00:00
if (minutes < 0 || seconds < 0) {
return '00:00';
}
// Format as MM:SS
return `${pad2(minutes)}:${pad2(seconds)}`;
});
const humanElapsed = computed(() => {
@@ -495,6 +501,121 @@ watch(() => nearestDepartment.value, (newValue) => {
}
});
/**
* Guided wash flow
*/
const guidedWashFlow = ref(true);
type guidedWashFlowBrushColor = 'is-black' | 'is-info' | 'is-link' | 'is-danger' | 'is-warning' | 'is-white';
type guidedWashFlowBrushes = {
label: string,
description: string,
warning?: string,
color: guidedWashFlowBrushColor,
position: 'left' | 'right',
}[];
type guidedWashFlowStep = {
title: string,
warning?: string,
content: string,
brushes: guidedWashFlowBrushes,
}
const guidedWashFlowSteps: guidedWashFlowStep[] = [
{
title: 'Højtryksforvask',
content: '',
warning: '',
brushes: [
{
label: 'Sort slange',
description: 'Spul med sort slange for at fjerne skidt.',
warning: 'Min. afstand til bil 20cm.',
color: 'is-black',
position: 'right',
},
],
},
{
title: 'Sæbe-pålægning',
content: 'Dæk bilen ind i sæbe',
brushes: [
{
label: 'Blå børste',
description: '',
color: 'is-info',
position: 'left',
},
],
},
{
title: 'Børstevask',
content: 'Børst for at fjerne resterende snavs.',
brushes: [
{
label: 'Blå børste',
description: 'Bruges til lakerede overflader.',
color: 'is-link',
position: 'left',
},
{
label: 'Rød børste',
description: 'Bruges til undervogn og fælge.',
color: 'is-danger',
position: 'right',
},
],
},
{
title: 'Højtryksskylning',
content: '',
brushes: [
{
label: 'Sort slange',
description: 'Spul med vand indtil sæben er væk.',
color: 'is-black',
position: 'right',
},
],
},
{
title: 'Voks pålægning',
content: '',
brushes: [
{
label: 'Gul slange',
description: 'Påfør voks på førerhuset.',
color: 'is-warning',
position: 'left',
},
],
},
{
title: 'Spot Free skylning',
content: '',
brushes: [
{
label: 'Hvid slange',
description: 'Skyl hurtigt førerhuset med Spot Free for at undgå pletter.',
color: 'is-white',
position: 'right',
},
],
}
];
const currentGuidedWashStep = ref(0);
const toggleGuidedWashFlow = () => {
guidedWashFlow.value = !guidedWashFlow.value;
};
const nextGuidedWashStep = () => {
if (currentGuidedWashStep.value < guidedWashFlowSteps.length - 1) {
currentGuidedWashStep.value += 1;
}
};
const previousGuidedWashStep = () => {
if (currentGuidedWashStep.value > 0) {
currentGuidedWashStep.value -= 1;
}
}
/**
* Watch for changes in the steps and update the localStorage accordingly.
*/
@@ -589,7 +710,7 @@ watch(() => currentStep.value, () => {
<b-step-item label="Start vask" iconPack="fas" icon="droplet" :step="steps.SELECT_LANE" :clickable="clickableSteps[steps.SELECT_LANE]()">
<h1 class="title has-text-centered">Start vask</h1>
<b-field label="Vaskebane">
<div class="columns is-multiline is-mobile is-centered">
<div class="columns is-multiline is-mobile" :class="{ 'is-centered': nearestDepartment && (nearestDepartment.lanes || []).length >= 2 }">
<template v-for="lane in nearestDepartment?.lanes || []" :key="lane">
<div class="column is-half-mobile is-one-third-tablet is-one-quarter-desktop">
<!-- Radio button for lane selection -->
@@ -679,6 +800,73 @@ watch(() => currentStep.value, () => {
<h2 class="subtitle has-text-centered">
<strong>{{ formattedElapsed }}</strong>
</h2>
<template v-if="guidedWashFlow">
<b-field label="Vasketrin">
<b-steps type="is-link" size="is-small" v-model="currentGuidedWashStep">
<b-step-item
v-for="(step, index) in guidedWashFlowSteps"
:key="index"
:label="currentGuidedWashStep === index ? step.title : ''"
:icon-pack="'fas'"
:icon="index === currentGuidedWashStep ? 'brush' : 'soap'"
:type="index === currentGuidedWashStep ? 'is-link' : 'is-light'"
:step="index"
>
<h3 class="title is-5 has-text-centered">{{ step.title }}</h3>
<!-- Warning -->
<div v-if="step.warning" class="notification is-warning is-light has-text-centered">
<span class="icon">
<i class="fas fa-exclamation-triangle fa-lg"></i>
</span>
<span class="ml-2"><strong>{{ step.warning }}</strong></span>
</div>
<!-- Brushes -->
<div class="columns is-centered">
<div
class="column is-narrow"
v-for="(brush, bIndex) in step.brushes"
:key="bIndex"
>
<div :class="['tag', 'is-medium', brush.color, 'mx-2', 'mb-0', 'mt-2']" style="display: flex; align-items: center; justify-content: center;">
<span class="icon is-large">
<i class="fas fa-droplet fa-lg"></i>
</span>
<span class="ml-1"><b>{{ brush.label }}</b></span>
</div>
<div class="is-block has-background-light p-2 mx-2" style="border-radius: 4px;">
<p class="has-text-centered mt-1">{{ brush.description }}</p>
</div>
<div v-show="brush.warning"
:class="['tag', 'is-medium', 'is-warning', 'mx-2', 'mb-0', 'mt-0']"
style="display: flex; align-items: center; justify-content: center; border-top-left-radius: 0; border-top-right-radius: 0;">
<span class="icon">
<i class="fas fa-exclamation-triangle fa-lg"></i>
</span>
<span><strong>{{ brush.warning }}</strong></span>
</div>
</div>
</div>
<p class="has-text-centered">{{ step.content }}</p>
<div class="buttons is-centered">
<b-button
type="is-link is-light"
icon-pack="fas"
icon-left="arrow-left"
:disabled="currentGuidedWashStep === 0"
@click="previousGuidedWashStep"
>Forrige</b-button>
<b-button
type="is-link"
icon-pack="fas"
icon-right="arrow-right"
:disabled="currentGuidedWashStep === guidedWashFlowSteps.length - 1"
@click="nextGuidedWashStep"
>Næste</b-button>
</div>
</b-step-item>
</b-steps>
</b-field>
</template>
<p class="has-text-centered">
Vasken er startet på bane {{ (currentLane && currentLane.name) ? currentLane.name : washLaneId }}.
Når vasken er færdig, skal du trykke på knappen "Færdig" nedenfor for at afslutte processen.
@@ -704,10 +892,11 @@ watch(() => currentStep.value, () => {
<!--{{ currentStep }}-->
<div class="buttons is-centered">
<b-button
v-show="currentStep !== steps.WASH_IN_PROGRESS && currentStep !== steps.COMPLETED"
type="is-link is-light"
icon-pack="fas"
icon-left="arrow-left"
:disabled="previous.disabled || currentStep === steps.COMPLETED"
:disabled="previous.disabled || currentStep === steps.COMPLETED || currentStep === steps.WASH_IN_PROGRESS"
@click.prevent="previous.action"
>
Forrige
@@ -743,6 +932,14 @@ watch(() => currentStep.value, () => {
:disabled="isNextButtonDisabled()"
@click="() => onStartWash(radioLaneOption, licensePlateInput, customerNumberInput)"
>Bekræft</b-button>
<!-- Guided wash button -->
<b-button
v-show="currentStep === steps.WASH_IN_PROGRESS"
type="is-link is-light"
icon-pack="fas"
icon-right="info-circle"
@click.prevent="toggleGuidedWashFlow"
>Vejledning</b-button>
<!-- Complete button -->
<b-button
v-show="currentStep === steps.WASH_IN_PROGRESS"