From 524be94afc4c5ee7819498b6283a854f45cfa2c5 Mon Sep 17 00:00:00 2001 From: Luca Haid Date: Mon, 8 Sep 2025 16:15:34 +0200 Subject: [PATCH] fixed bugs --- .../default/VueViews/WorkorderCompanyPWA.php | 352 +++++++++++------- public/js/pages/WorkorderBase/manifest.json | 4 +- 2 files changed, 222 insertions(+), 134 deletions(-) diff --git a/Layout/default/VueViews/WorkorderCompanyPWA.php b/Layout/default/VueViews/WorkorderCompanyPWA.php index ff6d04bdd..d2bf0fe3a 100644 --- a/Layout/default/VueViews/WorkorderCompanyPWA.php +++ b/Layout/default/VueViews/WorkorderCompanyPWA.php @@ -9,6 +9,7 @@ + @@ -22,6 +23,7 @@ window.TT_CONFIG = ; moment.locale('de'); tailwind.config = { + darkMode: 'class', // Enable dark mode based on a class theme: { extend: { colors: { @@ -34,10 +36,18 @@ - +
@@ -104,6 +112,10 @@ const selectedFcp = ref('all'); const isFcpSelectOpen = ref(false); const fcpSearchTerm = ref(''); + const fcpInputRef = ref(null); // For autofocusing FCP search + const isSettingsOpen = ref(false); + const theme = ref('system'); // 'light', 'dark', 'system' + const showThemePicker = ref(false); const API_BASE_URL = window.TT_CONFIG.BASE_PATH || '/WorkorderCompany'; @@ -155,51 +167,31 @@ const getStatusRank = (status) => { switch (status) { - // Priority 0: Active and scheduled, sorted by appointment date case 'scheduled': - case 'civil_engineering_completed': - return 0; - // Priority 1: New/Assigned tasks, sorted by deadline + case 'civil_engineering_completed': return 0; case 'assigned': case 'new': - case 'problem_solved': - return 1; - // Priority 2: Tasks with issues, sorted by deadline + case 'problem_solved': return 1; case 'intervention_required': case 'correction_requested': - case 'civil_engineering_required': - return 2; - // Priority 3: Finished tasks, sorted by deadline + case 'civil_engineering_required': return 2; case 'documented': - case 'completed': - return 3; - // Priority 4: Cancelled tasks - case 'cancelled': - return 4; - default: - return 99; // Fallback for any other status + case 'completed': return 3; + case 'cancelled': return 4; + default: return 99; } }; return filtered.sort((a, b) => { const rankA = getStatusRank(a.status); const rankB = getStatusRank(b.status); - - if (rankA !== rankB) { - return rankA - rankB; - } - - // For the highest priority group, sort by appointment date + if (rankA !== rankB) return rankA - rankB; if (rankA === 0) { const dateA = a.appointmentDate || Infinity; const dateB = b.appointmentDate || Infinity; - if (dateA === dateB) { - return (a.deadlineDate || Infinity) - (b.deadlineDate || Infinity); - } + if (dateA === dateB) return (a.deadlineDate || Infinity) - (b.deadlineDate || Infinity); return dateA - dateB; } - - // For all other groups, sort by deadline return (a.deadlineDate || Infinity) - (b.deadlineDate || Infinity); }); }); @@ -242,6 +234,28 @@ // --- METHODS --- + const applyTheme = () => { + const isDark = localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches); + document.documentElement.classList.toggle('dark', isDark); + const metaThemeColor = document.querySelector('meta[name="theme-color"]'); + if (metaThemeColor) { + metaThemeColor.setAttribute('content', isDark ? '#0f172a' : '#005384'); + } + }; + + const setTheme = (newTheme) => { + if (!['light', 'dark', 'system'].includes(newTheme)) return; + theme.value = newTheme; + if (newTheme === 'system') { + localStorage.removeItem('theme'); + } else { + localStorage.setItem('theme', newTheme); + } + applyTheme(); + isSettingsOpen.value = false; + if (showThemePicker.value) showThemePicker.value = false; + }; + const getStatusInfo = (status) => { const statuses = { 'new': { text: 'Neu', color: 'bg-blue-500' }, 'assigned': { text: 'Zugewiesen', color: 'bg-sky-500' }, @@ -364,13 +378,14 @@ for (const type of sortedInterventions) { let text = type.text; - if (text.includes('X')) { + const needsDetail = type.text.includes('X') || type.text.toLowerCase().includes('sonstiges'); + if (needsDetail) { const detail = problemModal.details[type.value] || ''; if (!detail) { alert(`Bitte geben Sie Details für "${type.text}" an.`); return; } - text = text.replace('X', detail); + text = text.includes('X') ? text.replace('X', detail) : `${text}: ${detail}`; } journalParts.push(text); } @@ -389,6 +404,8 @@ const handleCompleteClick = () => { if (isChecklistComplete.value) { + // Using a custom modal/confirm is better, but for now `confirm` is used. + // In a real PWA, you'd build a custom component to avoid blocking. if (confirm("Möchten Sie diesen Auftrag wirklich abschließen?")) { completeWorkorder(); } @@ -415,81 +432,97 @@ onMounted(() => { fetchWorkorders(); isStandalone.value = window.matchMedia('(display-mode: standalone)').matches; + + const savedTheme = localStorage.getItem('theme'); + if (savedTheme) { + theme.value = savedTheme; + } else { + showThemePicker.value = true; + } + applyTheme(); + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', applyTheme); }); watch(isFcpSelectOpen, (isOpen) => { - if (!isOpen) { + if (isOpen) { + nextTick(() => { + fcpInputRef.value?.focus(); + }); + } else { fcpSearchTerm.value = ''; } }); // Lock body scroll when any modal is open - watch([isDetailsPanelOpen, isFcpSelectOpen, uploadModal, problemModal, fullscreenViewer, installModal], ([details, fcp, upload, problem, viewer, install]) => { - const isAnyModalOpen = details || fcp || upload.show || problem.show || viewer.show || install.show; - if (isAnyModalOpen) { - document.body.style.overflow = 'hidden'; - } else { - document.body.style.overflow = ''; - } + watch([isDetailsPanelOpen, isFcpSelectOpen, isSettingsOpen, uploadModal, problemModal, fullscreenViewer, installModal, showThemePicker], (modals) => { + const isAnyModalOpen = modals.some(modal => (typeof modal === 'boolean' && modal) || (typeof modal === 'object' && modal.show)); + document.body.style.overflow = isAnyModalOpen ? 'hidden' : ''; }, { deep: true }); return { isLoading, isDetailsLoading, filteredWorkorders, searchTerm, isDetailsPanelOpen, selectedWorkorder, documentation, tenantConfig, tempAdditionalInfo, isEditingInfo, newJournalEntry, uploadModal, problemModal, isUploading, isChecklistComplete, checklist, fullscreenViewer, missingTasksPopover, translatedDocs, filteredJournals, installModal, isStandalone, - selectedFcp, isFcpSelectOpen, fcpOptions, selectedFcpText, fcpSearchTerm, filteredFcpOptions, fetchWorkorders, - openDetails, closeDetails, getStatusInfo, formatDate, googleMapsLink, startEditInfo, saveAdditionalInfo, - handleFileSelect, executeUpload, addJournalEntry, submitProblem, handleCompleteClick, selectFcp + selectedFcp, isFcpSelectOpen, fcpOptions, selectedFcpText, fcpSearchTerm, filteredFcpOptions, fcpInputRef, + isSettingsOpen, theme, showThemePicker, + fetchWorkorders, openDetails, closeDetails, getStatusInfo, formatDate, googleMapsLink, startEditInfo, saveAdditionalInfo, + handleFileSelect, executeUpload, addJournalEntry, submitProblem, handleCompleteClick, selectFcp, setTheme }; }, template: `
-
+
-
-
-
- Logo -
- -
+
+ Logo +
+
+ +
- -
-

Lade Aufträge...

-

Keine Aufträge gefunden.

+

Lade Aufträge...

+

Keine Aufträge gefunden.

-
+
-

#{{ wo.id }} | {{ wo.customerName || 'N/A' }}

-

{{ wo.street }} {{ wo.hausnummer }}, {{ wo.plz }} {{ wo.city }}

-
+

#{{ wo.id }} | {{ wo.customerName || 'N/A' }}

+

{{ wo.street }} {{ wo.hausnummer }}, {{ wo.plz }} {{ wo.city }}

+
OAID: {{ wo.oaid || 'N/A' }}
FCP: {{ wo.rimo_fcp_name || 'N/A' }}
{{ getStatusInfo(wo.status).text }} -

{{ formatDate(wo.appointmentDate, 'DD.MM HH:mm') }}

+

{{ formatDate(wo.appointmentDate, 'DD.MM HH:mm') }}

Frist: {{ formatDate(wo.deadlineDate) }}

@@ -499,87 +532,90 @@
-
-
-

Auftrag #{{ selectedWorkorder.id }}

- +
+
+
+ Logo +

Auftrag #{{ selectedWorkorder.id }}

+
+
-
-
- +
+
+ {{ selectedWorkorder.customerCompany || selectedWorkorder.customerName }}
{{ selectedWorkorder.street }} {{ selectedWorkorder.hausnummer }}, {{ selectedWorkorder.plz }} {{ selectedWorkorder.city }} -
+
-

OAID

-

{{ selectedWorkorder.oaid || 'N/A' }}

+

OAID

+

{{ selectedWorkorder.oaid || 'N/A' }}

-

FCP

-

{{ selectedWorkorder.rimo_fcp_name || 'N/A' }}

+

FCP

+

{{ selectedWorkorder.rimo_fcp_name || 'N/A' }}

- -
+
-

Notiz

-
- +
- +
-

{{ selectedWorkorder.additionalInfo || 'Keine Notiz.' }}

+

{{ selectedWorkorder.additionalInfo || 'Keine Notiz.' }}

-
-

Checkliste

+
+

Checkliste

-
-
+
+
  • - - {{ item.text }} + + {{ item.text }}
-

Keine Checklisten-Einträge vorhanden.

+

Keine Checklisten-Einträge vorhanden.

-
-

Dokumentation

-