358 lines
9.9 KiB
JavaScript
358 lines
9.9 KiB
JavaScript
import { computed, ref, watch } from "vue";
|
|
import {
|
|
buildSelfServeDynamicImageUrl,
|
|
getSelfServeCompletedDynamicImageStep,
|
|
getSelfServeDynamicImageButtonsToPress,
|
|
getSelfServeDynamicImageThumbPosition,
|
|
getSelfServeTaskDynamicImageButtons,
|
|
} from "@/services/selfServeDynamicImage.js";
|
|
|
|
export function useWashSessionActions(options) {
|
|
const {
|
|
request,
|
|
alertFn = (message) => window.alert(message),
|
|
nearestDepartment,
|
|
vehicleTypeSelect,
|
|
washLaneId,
|
|
washInProgress,
|
|
washStartTime,
|
|
completedDurationMs,
|
|
now,
|
|
currentStep,
|
|
steps,
|
|
radioWashType,
|
|
activeTasks,
|
|
completedTasks,
|
|
saveProgress,
|
|
clearProgress,
|
|
startElapsedTimer,
|
|
stopElapsedTimer,
|
|
updateLaneAllowedServices,
|
|
fetchWashSummary,
|
|
enableMachineRelay,
|
|
isServiceAllowed,
|
|
} = options;
|
|
|
|
const machineStartCurrentStep = ref(0);
|
|
const openingPropertyAccessGate = ref(false);
|
|
const openingPropertyExitGate = ref(false);
|
|
const isStartingWash = ref(false);
|
|
const lastCommandErrorMessage = ref(null);
|
|
|
|
const extractCommandErrorMessage = (
|
|
source,
|
|
fallback = "Der opstod en fejl ved udførelse af kommandoen. Prøv igen senere."
|
|
) => {
|
|
const candidates = [
|
|
source?.response?.data?.data?.message,
|
|
source?.response?.data?.message,
|
|
source?.response?.data?.error,
|
|
source?.data?.data?.message,
|
|
source?.data?.message,
|
|
source?.data?.error,
|
|
source?.message,
|
|
];
|
|
|
|
const message = candidates.find((candidate) => typeof candidate === "string" && candidate.trim() !== "");
|
|
|
|
return message || fallback;
|
|
};
|
|
|
|
const getTaskButtons = (task) => getSelfServeTaskDynamicImageButtons(task);
|
|
|
|
const getButtonsToPress = () => getSelfServeDynamicImageButtonsToPress(activeTasks.value);
|
|
|
|
const getCompletedButtons = () => {
|
|
const totalButtonsCompleted = getSelfServeCompletedDynamicImageStep(activeTasks.value, completedTasks.value);
|
|
machineStartCurrentStep.value = totalButtonsCompleted;
|
|
return totalButtonsCompleted;
|
|
};
|
|
|
|
const isAlreadyStoppedStopError = (message) => {
|
|
const normalized = String(message || "").toLowerCase();
|
|
return normalized.includes("cannot stop lane") && normalized.includes("not occupied");
|
|
};
|
|
|
|
const clearActiveWashState = () => {
|
|
completedDurationMs.value = washStartTime.value ? now.value - washStartTime.value : 0;
|
|
washInProgress.value = false;
|
|
washLaneId.value = null;
|
|
stopElapsedTimer();
|
|
clearProgress();
|
|
};
|
|
|
|
const dynamicImageUrl = computed(() => {
|
|
const departmentId = nearestDepartment.value?.id;
|
|
const laneId = washLaneId.value;
|
|
const lane = nearestDepartment.value?.lanes?.find((entry) => entry.id === laneId);
|
|
|
|
if (!departmentId || !laneId || !lane) {
|
|
return null;
|
|
}
|
|
|
|
return buildSelfServeDynamicImageUrl({
|
|
departmentId,
|
|
laneId,
|
|
buttons: getButtonsToPress(),
|
|
currentStep: getCompletedButtons(),
|
|
vehicleTypeId: vehicleTypeSelect.value,
|
|
thumbPosition: getSelfServeDynamicImageThumbPosition(activeTasks.value),
|
|
});
|
|
});
|
|
|
|
const executeSelfServeCommand = async (
|
|
laneId,
|
|
command,
|
|
args = {
|
|
customer_number: null,
|
|
license_plate: null,
|
|
},
|
|
options = {}
|
|
) => {
|
|
if (!nearestDepartment.value) {
|
|
alertFn("Ingen afdeling valgt.");
|
|
return null;
|
|
}
|
|
|
|
const { suppressAlert = false } = options;
|
|
lastCommandErrorMessage.value = null;
|
|
|
|
try {
|
|
const response = await request("/modules/self-serve/lane/command", "post", {
|
|
lane_id: laneId,
|
|
command,
|
|
...args,
|
|
});
|
|
const successValue = response?.data?.success ?? response?.success;
|
|
if (successValue === false) {
|
|
const message = extractCommandErrorMessage(response);
|
|
lastCommandErrorMessage.value = message;
|
|
if (!suppressAlert) {
|
|
alertFn(message);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
return response;
|
|
} catch (error) {
|
|
console.error(`Error executing command ${command} on lane ${laneId}:`, error);
|
|
const message = extractCommandErrorMessage(error);
|
|
lastCommandErrorMessage.value = message;
|
|
if (!suppressAlert) {
|
|
alertFn(message);
|
|
}
|
|
return null;
|
|
}
|
|
};
|
|
|
|
const resolveLaneId = (laneId = null, options = {}) => {
|
|
const { suppressAlert = false } = options;
|
|
const normalizedLaneId = Number.parseInt(String(laneId ?? washLaneId.value ?? ""), 10);
|
|
if (!Number.isInteger(normalizedLaneId) || normalizedLaneId <= 0) {
|
|
if (!suppressAlert) {
|
|
alertFn("Ingen vaskebane valgt.");
|
|
}
|
|
return null;
|
|
}
|
|
|
|
return normalizedLaneId;
|
|
};
|
|
|
|
const executePropertyGateCommand = async (command, laneId, loadingRef, options = {}) => {
|
|
if (loadingRef.value) {
|
|
return null;
|
|
}
|
|
|
|
loadingRef.value = true;
|
|
try {
|
|
const resolvedLaneId = resolveLaneId(laneId, options);
|
|
if (!resolvedLaneId) {
|
|
return null;
|
|
}
|
|
|
|
return await executeSelfServeCommand(
|
|
resolvedLaneId,
|
|
command,
|
|
{
|
|
customer_number: null,
|
|
license_plate: null,
|
|
},
|
|
options
|
|
);
|
|
} finally {
|
|
loadingRef.value = false;
|
|
}
|
|
};
|
|
|
|
const openPropertyAccessGate = async (laneId = null, options = {}) =>
|
|
executePropertyGateCommand("OPEN_PROPERTY_ACCESS_GATE", laneId, openingPropertyAccessGate, options);
|
|
|
|
const openPropertyExitGate = async (laneId = null, options = {}) =>
|
|
executePropertyGateCommand("OPEN_PROPERTY_EXIT_GATE", laneId, openingPropertyExitGate, options);
|
|
|
|
const rollbackStartedWash = async (laneId) => {
|
|
const stopResponse = await executeSelfServeCommand(
|
|
laneId,
|
|
"STOP",
|
|
{
|
|
customer_number: null,
|
|
license_plate: null,
|
|
},
|
|
{ suppressAlert: true }
|
|
);
|
|
|
|
if (!stopResponse) {
|
|
console.error(`Failed to roll back started wash on lane ${laneId}:`, lastCommandErrorMessage.value);
|
|
}
|
|
|
|
return stopResponse;
|
|
};
|
|
|
|
const onStartWash = async (laneId, licensePlate, customerNumber, targetStep = steps.WASH_IN_PROGRESS) => {
|
|
if (isStartingWash.value) {
|
|
return false;
|
|
}
|
|
|
|
if (washInProgress.value && currentStep.value === targetStep) {
|
|
return true;
|
|
}
|
|
|
|
if (washInProgress.value) {
|
|
currentStep.value = targetStep;
|
|
return true;
|
|
}
|
|
|
|
if (!nearestDepartment.value) {
|
|
alertFn("Ingen afdeling valgt.");
|
|
return false;
|
|
}
|
|
|
|
if (!licensePlate || licensePlate.trim() === "") {
|
|
alertFn("Indtast venligst et registreringsnummer.");
|
|
return false;
|
|
}
|
|
|
|
if (!parseInt(customerNumber)) {
|
|
alertFn("Indtast venligst et kundenummer.");
|
|
return false;
|
|
}
|
|
|
|
isStartingWash.value = true;
|
|
try {
|
|
try {
|
|
await updateLaneAllowedServices(laneId);
|
|
} catch (error) {
|
|
console.error("Error updating allowed services before start:", error);
|
|
alertFn(extractCommandErrorMessage(error, "Der opstod en fejl ved klargøring af vasken. Prøv igen senere."));
|
|
return false;
|
|
}
|
|
|
|
const startResponse = await executeSelfServeCommand(laneId, "START", {
|
|
customer_number: parseInt(customerNumber),
|
|
license_plate: licensePlate.trim().toUpperCase(),
|
|
defer_relay_side_effects: false,
|
|
});
|
|
if (!startResponse) {
|
|
return false;
|
|
}
|
|
|
|
if (radioWashType.value === "Machine" && isServiceAllowed("MACHINE")) {
|
|
let machineRelayResponse = null;
|
|
try {
|
|
machineRelayResponse = await enableMachineRelay(laneId);
|
|
} catch (error) {
|
|
console.error("Error enabling machine relay after wash start:", error);
|
|
await rollbackStartedWash(laneId);
|
|
alertFn(extractCommandErrorMessage(error, "Kunne ikke starte maskinen. Prøv igen."));
|
|
return false;
|
|
}
|
|
|
|
const machineRelaySuccessValue = machineRelayResponse?.data?.success ?? machineRelayResponse?.success;
|
|
if (machineRelaySuccessValue === false) {
|
|
await rollbackStartedWash(laneId);
|
|
alertFn(extractCommandErrorMessage(machineRelayResponse, "Kunne ikke starte maskinen. Prøv igen."));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
washLaneId.value = laneId;
|
|
washStartTime.value = Date.now();
|
|
completedDurationMs.value = null;
|
|
washInProgress.value = true;
|
|
startElapsedTimer();
|
|
currentStep.value = targetStep;
|
|
saveProgress("onStartWash");
|
|
|
|
await fetchWashSummary({
|
|
lane_id: laneId,
|
|
reg: licensePlate.trim().toUpperCase(),
|
|
});
|
|
|
|
return true;
|
|
} catch (error) {
|
|
console.error("Error starting self-serve wash:", error);
|
|
alertFn(extractCommandErrorMessage(error, "Der opstod en fejl ved start af vasken. Prøv igen senere."));
|
|
return false;
|
|
} finally {
|
|
isStartingWash.value = false;
|
|
}
|
|
};
|
|
|
|
const onStopWash = async (laneId) => {
|
|
if (!nearestDepartment.value) {
|
|
alertFn("Ingen afdeling valgt.");
|
|
return false;
|
|
}
|
|
|
|
if (!washInProgress.value) {
|
|
alertFn("Ingen vask er i gang.");
|
|
return false;
|
|
}
|
|
|
|
const stopResponse = await executeSelfServeCommand(
|
|
laneId,
|
|
"STOP",
|
|
{
|
|
customer_number: null,
|
|
license_plate: null,
|
|
},
|
|
{ suppressAlert: true }
|
|
);
|
|
if (!stopResponse) {
|
|
if (isAlreadyStoppedStopError(lastCommandErrorMessage.value)) {
|
|
clearActiveWashState();
|
|
return true;
|
|
}
|
|
|
|
alertFn(lastCommandErrorMessage.value || "Der opstod en fejl ved udførelse af kommandoen. Prøv igen senere.");
|
|
return false;
|
|
}
|
|
|
|
clearActiveWashState();
|
|
return true;
|
|
};
|
|
|
|
watch(
|
|
[completedTasks, activeTasks],
|
|
() => {
|
|
getCompletedButtons();
|
|
},
|
|
{ deep: true }
|
|
);
|
|
|
|
return {
|
|
machineStartCurrentStep,
|
|
dynamicImageUrl,
|
|
getButtonsToPress,
|
|
getCompletedButtons,
|
|
executeSelfServeCommand,
|
|
onStartWash,
|
|
onStopWash,
|
|
openPropertyAccessGate,
|
|
openPropertyExitGate,
|
|
openingPropertyAccessGate,
|
|
openingPropertyExitGate,
|
|
isStartingWash,
|
|
};
|
|
}
|