Refactor self-serve task list to improve task title handling and remove unnecessary description checks

This commit is contained in:
Jeppe Bundgaard
2026-06-02 20:03:55 +02:00
parent 42dfdfef13
commit 74a7c9f23f
4 changed files with 58 additions and 24 deletions
@@ -21,16 +21,6 @@ const isImageAttachment = (attachment: any) => (
&& attachment.content.other.match(/\.(jpg|jpeg|png|gif|webp|svg)$/i)
);
const hasTaskDescription = (task: any) => {
const description = task?.description;
if (typeof description !== "string") {
return !!description;
}
const trimmedDescription = description.trim();
return trimmedDescription.length > 0 && trimmedDescription !== "-";
};
const getImageAttachments = (task: any) => {
if (!Array.isArray(task?.attachments)) {
return [];
@@ -83,7 +73,7 @@ const formatTaskTitle = (task: any) => {
const title = String(task?.task || "");
const programWheelSelection = getProgramWheelSelection(task);
if (programWheelSelection === null) {
if (programWheelSelection === null || /\bprogram\s*#\d+\b/i.test(title)) {
return title;
}
@@ -133,7 +123,6 @@ const formatTaskTitle = (task: any) => {
</div>
<div class="self-serve-task-image-overlay-text">
<p class="self-serve-task-title"><strong>{{ formatTaskTitle(task) }}</strong></p>
<p v-if="hasTaskDescription(task)" class="self-serve-task-description">{{ task.description }}</p>
</div>
</div>
</div>
@@ -156,8 +145,8 @@ const formatTaskTitle = (task: any) => {
</div>
</div>
</template>
<div v-else class="columns is-mobile is-vcentered">
<div v-if="props.showCheckboxes" class="column is-narrow">
<div v-else class="self-serve-task-row">
<div v-if="props.showCheckboxes" class="self-serve-task-checkbox">
<b-field>
<b-checkbox
size="is-large"
@@ -169,9 +158,8 @@ const formatTaskTitle = (task: any) => {
/>
</b-field>
</div>
<div class="column">
<div class="self-serve-task-content">
<p><strong>{{ formatTaskTitle(task) }}</strong></p>
<p v-if="hasTaskDescription(task)" class="is-size-7">{{ task.description }}</p>
<div v-if="getVisibleServices(task).length > 0" class="tags mt-2">
<span v-for="service in getVisibleServices(task)" :key="service" class="tag is-success">{{ service }}</span>
</div>
@@ -239,7 +227,7 @@ const formatTaskTitle = (task: any) => {
padding: 0.65rem 0.75rem;
display: flex;
align-items: flex-start;
gap: 0.6rem;
gap: 0.35rem;
pointer-events: auto;
}
@@ -247,12 +235,30 @@ const formatTaskTitle = (task: any) => {
margin-bottom: 0;
}
.self-serve-task-row {
display: flex;
align-items: center;
gap: 0.35rem;
}
.self-serve-task-checkbox {
flex: 0 0 auto;
}
.self-serve-task-checkbox :deep(.field) {
margin-bottom: 0;
}
.self-serve-task-content {
flex: 1 1 auto;
min-width: 0;
}
.self-serve-task-content p {
margin-bottom: 0;
}
.self-serve-task-title {
margin: 0;
}
.self-serve-task-description {
margin: 0.25rem 0 0;
font-size: 0.85rem;
}
</style>
+4 -1
View File
@@ -15,6 +15,7 @@ export function useWashFlowState(options) {
licensePlateInput,
vehicleTypeSelect,
availableProductIds,
isCustomerNumberRequired,
radioLaneOption,
nearestDepartment,
allVisibleQuestionsAnswered,
@@ -46,7 +47,9 @@ export function useWashFlowState(options) {
&& selectedVehicleTypeId !== undefined
&& allowedProductIds.has(String(selectedVehicleTypeId));
const customerNumberValue = customerNumberInput.value;
const customerNumberValid = customerNumberValue === null
const requiresCustomerNumber = isCustomerNumberRequired?.value ?? false;
const customerNumberValid = !requiresCustomerNumber
|| customerNumberValue === null
|| customerNumberValue === undefined
|| String(customerNumberValue).trim() !== "";
const licensePlateValid = !!(licensePlateInput.value && licensePlateInput.value.trim() !== "");
+12 -1
View File
@@ -62,9 +62,10 @@ describe("SelfServeTaskList", () => {
]);
expect(wrapper.text()).not.toContain("MACHINE");
expect(wrapper.text()).not.toContain("Button 1");
expect(wrapper.text()).not.toContain("Use the soft brush");
});
it("prefixes only program picker task titles with the configured wheel selection", () => {
it("adds the configured wheel selection only when the program title does not already include it", () => {
const wrapper = mountWithApp(SelfServeTaskList, {
props: {
tasks: [
@@ -76,6 +77,14 @@ describe("SelfServeTaskList", () => {
buttons: [],
dynamic_images_vehicle_type: 4,
},
{
id: 10,
task: "Vælg program #1 på dial",
description: "-",
services: ["PROGRAM_PICKER"],
buttons: [],
dynamic_images_vehicle_type: 1,
},
{
id: 7,
task: "Tryk reset",
@@ -113,6 +122,8 @@ describe("SelfServeTaskList", () => {
});
expect(wrapper.get('[data-testid="self-serve-task-6"]').text()).toContain("Choose program #4");
expect(wrapper.get('[data-testid="self-serve-task-10"]').text()).toContain("Vælg program #1 på dial");
expect(wrapper.get('[data-testid="self-serve-task-10"]').text()).not.toContain("program #1 #1");
expect(wrapper.get('[data-testid="self-serve-task-7"]').text()).toContain("Tryk reset");
expect(wrapper.get('[data-testid="self-serve-task-7"]').text()).not.toContain("#");
expect(wrapper.get('[data-testid="self-serve-task-9"]').text()).toContain("Choose by button #3");
+14
View File
@@ -51,6 +51,20 @@ describe("useWashFlowState", () => {
expect(flow.clickableSteps[WASH_STEPS.VEHICLE]()).toBe(false);
});
it("does not require a customer number when the customer number input is hidden", () => {
const { flow, state } = createState({
customerNumberInput: ref(""),
isCustomerNumberRequired: ref(false),
});
expect(flow.clickableSteps[WASH_STEPS.VEHICLE]()).toBe(true);
expect(flow.isNextButtonDisabled()).toBe(false);
state.isCustomerNumberRequired.value = true;
expect(flow.clickableSteps[WASH_STEPS.VEHICLE]()).toBe(false);
expect(flow.isNextButtonDisabled()).toBe(true);
});
it("moves from questions to lane selection after updating allowed services", async () => {
const { flow, state } = createState({
currentStep: ref(WASH_STEPS.QUESTIONS),