added technical data to xinon workorder and workordermph now has a unassign button

This commit is contained in:
Luca Haid
2026-01-18 17:42:11 +00:00
parent a35b865fad
commit 6ab41a9169
13 changed files with 508 additions and 24 deletions

View File

@@ -31,6 +31,7 @@ export default {
const documentation = ref({ docs: [], journals: [] });
const tenantConfig = ref(null);
const checklist = ref([]);
const technicalData = ref(null);
// Expanded cards state
const expandedCards = ref({
@@ -39,7 +40,8 @@ export default {
documentation: false,
notes: false,
journal: false,
cableData: false
cableData: false,
technical: true
});
// Edit states
@@ -52,6 +54,9 @@ export default {
const showDocUploadSheet = ref(false);
const showProblemSheet = ref(false);
const showCompleteSheet = ref(false);
const showPdfViewer = ref(false);
const pdfViewerUrl = ref('');
const pdfViewerTitle = ref('');
// Upload state
const uploadDocType = ref('');
@@ -198,7 +203,7 @@ export default {
const openDetail = async (workorder) => {
selectedWorkorder.value = workorder;
isDetailLoading.value = true;
expandedCards.value = { customer: true, checklist: true, documentation: false, notes: false, journal: false, cableData: false };
expandedCards.value = { customer: true, checklist: true, documentation: false, notes: false, journal: false, cableData: false, technical: true };
emit('detail-open', workorder.id);
try {
@@ -215,6 +220,7 @@ export default {
documentation.value = { docs: data.docs, journals: data.journals };
tenantConfig.value = data.tenantConfig;
checklist.value = data.checklist;
technicalData.value = data.technicalData || null;
} else {
emit('toast', data.message || 'Fehler beim Laden', 'error');
}
@@ -231,6 +237,7 @@ export default {
documentation.value = { docs: [], journals: [] };
tenantConfig.value = null;
checklist.value = [];
technicalData.value = null;
isEditingNotes.value = false;
emit('detail-close');
};
@@ -617,6 +624,13 @@ export default {
// Button is disabled when not complete, so this won't be called
};
// Open PDF in viewer
const openPdfViewer = (url, title) => {
pdfViewerUrl.value = url;
pdfViewerTitle.value = title || 'PDF';
showPdfViewer.value = true;
};
// Initialize
onMounted(() => {
fetchWorkorders();
@@ -636,6 +650,7 @@ export default {
documentation,
tenantConfig,
checklist,
technicalData,
expandedCards,
isEditingNotes,
tempNotes,
@@ -644,6 +659,9 @@ export default {
showDocUploadSheet,
showProblemSheet,
showCompleteSheet,
showPdfViewer,
pdfViewerUrl,
pdfViewerTitle,
uploadDocType,
isUploading,
fileInputRef,
@@ -678,6 +696,7 @@ export default {
openNavigation,
callCustomer,
handleComplete,
openPdfViewer,
handleTouchStart,
handleTouchMove,
handleTouchEnd,
@@ -906,6 +925,63 @@ export default {
</div>
</div>
<!-- Technical Data Card -->
<div v-if="technicalData && (technicalData.patchposition?.equipmentName || technicalData.rimoWorkorders?.length)"
class="bg-white dark:bg-slate-800 rounded-xl overflow-hidden card-contrast">
<button
@click="toggleCard('technical')"
class="w-full flex items-center justify-between p-4 text-left"
>
<div class="flex items-center">
<div class="w-8 h-8 bg-purple-500/10 rounded-lg flex items-center justify-center mr-3">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-purple-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z"/>
</svg>
</div>
<span class="font-semibold text-slate-800 dark:text-white">Technische Daten</span>
</div>
<svg xmlns="http://www.w3.org/2000/svg" :class="['h-5 w-5 text-slate-400 transition-transform', expandedCards.technical ? 'rotate-180' : '']" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
</button>
<div v-if="expandedCards.technical" class="px-4 pb-4 space-y-3">
<!-- Patchposition -->
<div v-if="technicalData.patchposition?.equipmentName" class="space-y-2">
<div class="text-sm font-medium text-slate-500 dark:text-slate-400">Patchposition</div>
<div class="bg-slate-50 dark:bg-slate-700/50 rounded-lg p-3 space-y-1">
<div class="flex justify-between">
<span class="text-slate-500 dark:text-slate-400 text-sm">Equipment Name:</span>
<span class="font-mono text-slate-900 dark:text-white">{{ technicalData.patchposition.equipmentName }}</span>
</div>
<div v-if="technicalData.patchposition.equipmentPort" class="flex justify-between">
<span class="text-slate-500 dark:text-slate-400 text-sm">Equipment Port:</span>
<span class="font-mono text-slate-900 dark:text-white">{{ technicalData.patchposition.equipmentPort }}</span>
</div>
</div>
</div>
<!-- AHA Blätter -->
<div v-if="technicalData.rimoWorkorders?.length" class="space-y-2">
<div class="text-sm font-medium text-slate-500 dark:text-slate-400">AHA Blätter</div>
<div v-for="wo in technicalData.rimoWorkorders" :key="wo.id"
class="bg-slate-50 dark:bg-slate-700/50 rounded-lg p-3 flex items-center justify-between">
<div>
<div class="font-medium text-slate-900 dark:text-white">{{ wo.rimoName }}</div>
<div class="text-xs text-slate-500 dark:text-slate-400">Status: {{ wo.rimoStatus }}</div>
</div>
<button @click="openPdfViewer(wo.downloadUrl, wo.rimoName)"
class="flex items-center gap-2 px-3 py-2 bg-primary text-white rounded-lg text-sm font-medium active:scale-95 transition">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/>
</svg>
AHA
</button>
</div>
</div>
</div>
</div>
<!-- Checklist Card -->
<div class="bg-white dark:bg-slate-800 rounded-xl overflow-hidden card-contrast">
<button
@@ -1373,6 +1449,40 @@ export default {
</transition>
</teleport>
<!-- PDF Viewer Modal -->
<teleport to="body">
<transition name="fade">
<div v-if="showPdfViewer" class="fixed inset-0 z-50 flex flex-col bg-white dark:bg-slate-900">
<!-- Header -->
<div class="flex items-center justify-between px-4 py-3 bg-white dark:bg-slate-800 border-b border-slate-200 dark:border-slate-700 flex-shrink-0" style="padding-top: calc(0.75rem + env(safe-area-inset-top, 0px));">
<h3 class="text-lg font-semibold text-slate-800 dark:text-white truncate flex-1 mr-4">{{ pdfViewerTitle }}</h3>
<button @click="showPdfViewer = false" class="p-2 -mr-2 text-slate-500 dark:text-slate-400 hover:text-slate-700 dark:hover:text-slate-200">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<!-- PDF Content -->
<div class="flex-1 overflow-hidden bg-slate-100 dark:bg-slate-800">
<iframe
:src="pdfViewerUrl + (pdfViewerUrl.includes('?') ? '&' : '?') + 'inline=1'"
class="w-full h-full border-0"
style="min-height: 100%;"
></iframe>
</div>
<!-- Footer with download option -->
<div class="flex-shrink-0 px-4 py-3 bg-white dark:bg-slate-800 border-t border-slate-200 dark:border-slate-700" style="padding-bottom: calc(0.75rem + env(safe-area-inset-bottom, 0px));">
<a :href="pdfViewerUrl" download class="w-full py-3 bg-primary text-white rounded-xl font-medium flex items-center justify-center gap-2">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
</svg>
Download
</a>
</div>
</div>
</transition>
</teleport>
<input
ref="fileInputRef"
type="file"