added new rml stuff

This commit is contained in:
Luca Haid
2025-11-03 12:59:00 +01:00
parent 37be99b284
commit 887552a734
7 changed files with 306 additions and 20 deletions

View File

@@ -115,6 +115,7 @@
const isSettingsOpen = ref(false);
const theme = ref('system'); // 'light', 'dark', 'system'
const showThemePicker = ref(false);
const savingData = ref(false); // <-- ADDED
const API_BASE_URL = window.TT_CONFIG.BASE_PATH || '/WorkorderCompany';
@@ -211,9 +212,24 @@
});
});
// MODIFIED
const isChecklistComplete = computed(() => {
if (checklist.value.length === 0) return true;
return checklist.value.every(item => item.completed);
// Check documents
if (checklist.value.length > 0) {
if (!checklist.value.every(item => item.completed)) {
return false;
}
}
// Check new fields
if (tenantConfig.value?.requireCableLength && (!selectedWorkorder.value.cableLength || !selectedWorkorder.value.cableLength.trim())) {
return false;
}
if (tenantConfig.value?.requireCableType && (!selectedWorkorder.value.cableType || !selectedWorkorder.value.cableType.trim())) {
return false;
}
return true; // All checks passed
});
const translatedDocs = computed(() => {
@@ -291,7 +307,7 @@
documentation.docs = docRes.data.docs.map(d => ({...d, isPdf: d.mimetype === 'application/pdf'}));
documentation.journals = docRes.data.journals;
if (configRes.data.success) {
tenantConfig.value = configRes.data;
tenantConfig.value = configRes.data; // <-- MODIFIED: This will now contain all flags
}
} catch (e) { console.error("Could not load details", e); }
finally { isDetailsLoading.value = false; }
@@ -329,6 +345,36 @@
finally { isEditingInfo.value = false; }
};
// START ADDED
const saveWorkorderData = async () => {
savingData.value = true;
try {
const response = await api.post('/updateWorkorderData', {
workorderId: selectedWorkorder.value.id,
cableLength: selectedWorkorder.value.cableLength,
cableType: selectedWorkorder.value.cableType
});
if (response.data.success) {
alert('Daten gespeichert.'); // PWA uses alert()
documentation.journals = response.data.journals; // Update journal
// Also update the main list item
const woInList = workorders.value.find(w => w.id === selectedWorkorder.value.id);
if (woInList) {
woInList.cableLength = selectedWorkorder.value.cableLength;
woInList.cableType = selectedWorkorder.value.cableType;
}
} else {
alert(response.data.message || 'Speichern fehlgeschlagen.');
}
} catch (e) {
console.error("Failed to save data", e);
alert('Ein Netzwerkfehler ist aufgetreten.');
} finally {
savingData.value = false;
}
};
// END ADDED
const addJournalEntry = async () => {
if (!newJournalEntry.value.trim()) return;
try {
@@ -401,13 +447,23 @@
finally { problemModal.show = false; problemModal.selectedInterventions = []; problemModal.details = {}; }
};
// MODIFIED
const handleCompleteClick = () => {
if (isChecklistComplete.value) {
if (confirm("Möchten Sie diesen Auftrag wirklich abschließen?")) {
completeWorkorder();
}
} else {
missingTasksPopover.tasks = checklist.value.filter(t => !t.completed).map(t => t.text);
const missingDocs = checklist.value.filter(t => !t.completed).map(t => t.text);
const missingData = [];
if (tenantConfig.value?.requireCableLength && (!selectedWorkorder.value.cableLength || !selectedWorkorder.value.cableLength.trim())) {
missingData.push("Kabellänge");
}
if (tenantConfig.value?.requireCableType && (!selectedWorkorder.value.cableType || !selectedWorkorder.value.cableType.trim())) {
missingData.push("Kabeltyp");
}
missingTasksPopover.tasks = [...missingDocs, ...missingData];
missingTasksPopover.show = true;
setTimeout(() => missingTasksPopover.show = false, 4000);
}
@@ -415,10 +471,18 @@
const completeWorkorder = async () => {
try {
await api.post('/completeWorkorder', { workorderId: selectedWorkorder.value.id });
await fetchWorkorders();
closeDetails();
} catch(e) { console.error("Failed to complete workorder", e); }
// Server-side validation will catch errors if client-side check fails
const response = await api.post('/completeWorkorder', { workorderId: selectedWorkorder.value.id });
if (response.data.success) {
await fetchWorkorders();
closeDetails();
} else {
alert(response.data.message); // Show validation error from server
}
} catch(e) {
console.error("Failed to complete workorder", e);
alert(e.response?.data?.message || 'Fehler beim Abschließen.');
}
};
const selectFcp = (fcpValue) => {
@@ -456,8 +520,10 @@
checklist, fullscreenViewer, missingTasksPopover, translatedDocs, filteredJournals, installModal, isStandalone,
selectedFcp, isFcpSelectOpen, fcpOptions, selectedFcpText, fcpSearchTerm, filteredFcpOptions, fcpInputRef,
isSettingsOpen, theme, showThemePicker,
savingData, // <-- ADDED
fetchWorkorders, openDetails, closeDetails, getStatusInfo, formatDate, googleMapsLink, startEditInfo, saveAdditionalInfo,
handleFileSelect, executeUpload, addJournalEntry, submitProblem, handleCompleteClick, selectFcp, setTheme
handleFileSelect, executeUpload, addJournalEntry, submitProblem, handleCompleteClick, selectFcp, setTheme,
saveWorkorderData // <-- ADDED
};
},
template: `
@@ -593,6 +659,20 @@
<p v-else class="text-sm whitespace-pre-wrap text-slate-800 dark:text-slate-200">{{ selectedWorkorder.additionalInfo || 'Keine Notiz.' }}</p>
</div>
<div v-if="tenantConfig && (tenantConfig.requireCableLength || tenantConfig.requireCableType)" class="bg-white dark:bg-slate-900 p-4 rounded-lg border border-slate-200 dark:border-slate-800 space-y-3 text-sm">
<h3 class="font-bold text-slate-700 dark:text-secondary">Zusatzdaten</h3>
<div v-if="tenantConfig.requireCableLength">
<label class="text-xs text-slate-500 dark:text-slate-300 font-semibold">Kabellänge (m)</label>
<input v-model="selectedWorkorder.cableLength" type="text" class="mt-1 w-full p-2 border rounded-md dark:bg-slate-800 dark:border-slate-700 dark:text-white" placeholder="z.B. 20m">
</div>
<div v-if="tenantConfig.requireCableType">
<label class="text-xs text-slate-500 dark:text-slate-300 font-semibold">Kabeltyp</label>
<input v-model="selectedWorkorder.cableType" type="text" class="mt-1 w-full p-2 border rounded-md dark:bg-slate-800 dark:border-slate-700 dark:text-white" placeholder="z.B. LWL-Kabel 4F">
</div>
<button @click="saveWorkorderData" :disabled="savingData" class="mt-2 w-full px-4 py-2 bg-secondary text-primary font-bold rounded-md text-sm disabled:bg-slate-300">
{{ savingData ? 'Speichert...' : 'Daten speichern' }}
</button>
</div>
<div class="bg-white dark:bg-slate-900 p-4 rounded-lg border border-slate-200 dark:border-slate-800">
<h3 class="font-bold text-slate-700 dark:text-secondary mb-3">Checkliste</h3>
<div v-if="isDetailsLoading" class="space-y-3 animate-pulse">
@@ -672,7 +752,7 @@
<button @click="handleCompleteClick" class="w-full px-4 py-3 bg-green-600 text-white font-bold rounded-md text-center disabled:bg-slate-300">Abschließen</button>
<transition name="fade">
<div v-if="missingTasksPopover.show" class="absolute bottom-full right-0 mb-2 w-72 bg-red-700 text-white text-sm rounded-lg shadow-lg p-3">
<h4 class="font-bold mb-1">Fehlende Checklisten-Punkte:</h4>
<h4 class="font-bold mb-1">Fehlende Punkte:</h4>
<ul class="list-disc list-inside space-y-1">
<li v-for="task in missingTasksPopover.tasks" :key="task">{{ task }}</li>
</ul>
@@ -870,4 +950,4 @@
</script>
<script src="/js/pages/WorkorderBase/WorkorderServiceWorker.js"></script>
</body>
</html>
</html>