Tickets auf WEBklar zugeschnitten (Paket B)
- Status: 6 statt 10, auf Deutsch (Offen, In Arbeit, Wartet auf Kunde,
Prüfung, Erledigt, Storniert). Gespeichert werden die Werte, die das
Kundenportal für die Fortschrittsleiste kennt; alte Werte wie Assigned
werden weiter angezeigt ("Eingeplant"), sind aber nicht mehr wählbar.
- Zuweisen ändert den Status nicht mehr; neue Tickets starten "Offen".
- Priorität: Schalter "Dringend" statt fünf Stufen (dringend = 4, normal
= 2; alte Stufen Hoch/Kritisch gelten als dringend), rotes Abzeichen.
- Ticketliste: Standardansicht "Aufträge" ohne Akquise-Tickets; Filter
Typ (Aufträge/Webpage/Migration/Projekt/Akquise/Alle), 6 Status-Gruppen,
"Nur dringende". Die toten Felder Kunde, Benutzer/Thema und Datum sind
durch eine echte Suche ersetzt (Kunde, Betreff, Angefragt von, WOID).
Deep-Link ?woid= zeigt das Ticket weiter unabhängig von Art und Status.
- Formulare "Neues Ticket" und "Arbeitsblatt" auf Deutsch; raus sind
Workload Estimate, Requested for und die Service-Art am Ticket
(gespeichert wird weiter Fernwartung).
- Ticketkarte: Projekt/Preview im Details-Reiter (4 statt 5 Reiter), eine
Zusammenfassungszeile statt der großen Statistik, doppelter
Projekte-Stift weg, Service-Abzeichen weg.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
bf007df737
commit
062d992b63
17 files changed
+359
-626
No files matched your search
+28
-26
@@ -1,5 +1,6 @@
|
||||
import { useState, useEffect, useCallback, useMemo } from 'react'
|
||||
import { databases, DATABASE_ID, COLLECTIONS, Query, ID } from '../lib/appwrite'
|
||||
import { ticketMatches, NORMAL_PRIORITY } from '../lib/ticketStatus'
|
||||
|
||||
function buildFiltersKey(filters = {}) {
|
||||
return JSON.stringify({
|
||||
@@ -10,6 +11,8 @@ function buildFiltersKey(filters = {}) {
|
||||
type: filters.type ?? null,
|
||||
priority: filters.priority ?? null,
|
||||
woid: filters.woid ?? null,
|
||||
excludeType: filters.excludeType ?? null,
|
||||
search: filters.search ?? null,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -25,6 +28,8 @@ export function useWorkorders(filters = {}) {
|
||||
filters.type,
|
||||
filters.priority,
|
||||
filters.woid,
|
||||
filters.excludeType,
|
||||
filters.search,
|
||||
])
|
||||
|
||||
const fetchWorkorders = useCallback(async () => {
|
||||
@@ -33,8 +38,11 @@ export function useWorkorders(filters = {}) {
|
||||
|
||||
try {
|
||||
const queries = [Query.orderDesc('$createdAt')]
|
||||
|
||||
if (activeFilters.limit) {
|
||||
|
||||
// Die Suche laeuft hier im Browser ueber alle Tickets, die zu den Filtern passen
|
||||
if (activeFilters.search) {
|
||||
queries.push(Query.limit(5000))
|
||||
} else if (activeFilters.limit) {
|
||||
queries.push(Query.limit(activeFilters.limit))
|
||||
}
|
||||
|
||||
@@ -49,6 +57,11 @@ export function useWorkorders(filters = {}) {
|
||||
queries.push(Query.equal('type', activeFilters.type))
|
||||
}
|
||||
|
||||
// Standardansicht "Auftraege": alles ausser Akquise-Tickets
|
||||
if (activeFilters.excludeType) {
|
||||
queries.push(Query.notEqual('type', activeFilters.excludeType))
|
||||
}
|
||||
|
||||
if (activeFilters.priority && activeFilters.priority.length > 0) {
|
||||
queries.push(Query.equal('priority', activeFilters.priority))
|
||||
}
|
||||
@@ -80,7 +93,11 @@ export function useWorkorders(filters = {}) {
|
||||
queries
|
||||
)
|
||||
|
||||
setWorkorders(response.documents)
|
||||
setWorkorders(
|
||||
activeFilters.search
|
||||
? response.documents.filter((ticket) => ticketMatches(ticket, activeFilters.search))
|
||||
: response.documents
|
||||
)
|
||||
setError(null)
|
||||
} catch (err) {
|
||||
let errorMessage = err.message || 'Fehler beim Laden der Tickets'
|
||||
@@ -155,18 +172,18 @@ export function useWorkorders(filters = {}) {
|
||||
try {
|
||||
// Validierung: Prüfe required fields
|
||||
if (!data.topic || data.topic.trim() === '') {
|
||||
return { success: false, error: 'Das Feld "Topic" ist erforderlich.' }
|
||||
return { success: false, error: 'Bitte einen Betreff eingeben.' }
|
||||
}
|
||||
|
||||
const automatic = await resolveAutomaticTicketFields(data.assignedTo)
|
||||
const autoStatus = automatic.assignedTo ? 'Assigned' : 'Open'
|
||||
|
||||
// Bereite Daten für Appwrite vor
|
||||
|
||||
// Bereite Daten für Appwrite vor. Neue Tickets starten "Offen", auch wenn sie
|
||||
// gleich jemandem zugewiesen werden - wer zustaendig ist, zeigt das Kuerzel.
|
||||
const workorderData = {
|
||||
// Required fields
|
||||
topic: data.topic.trim(),
|
||||
status: autoStatus,
|
||||
priority: typeof data.priority === 'number' ? data.priority : parseInt(data.priority) || 1,
|
||||
status: 'Open',
|
||||
priority: typeof data.priority === 'number' ? data.priority : parseInt(data.priority) || NORMAL_PRIORITY,
|
||||
woid: automatic.woid,
|
||||
|
||||
// Optional fields - nur senden wenn vorhanden
|
||||
@@ -228,27 +245,12 @@ export function useWorkorders(filters = {}) {
|
||||
|
||||
const updateWorkorder = async (id, data) => {
|
||||
try {
|
||||
// Status-Automatik beim Update:
|
||||
// Wenn assignedTo gesetzt wird → Status = "Assigned"
|
||||
// Wenn assignedTo entfernt wird UND Status = "Assigned" → Status = "Open"
|
||||
const updateData = { ...data }
|
||||
if ('assignedTo' in updateData) {
|
||||
if (updateData.assignedTo && updateData.assignedTo !== '') {
|
||||
// Mitarbeiter zugewiesen → Status auf "Assigned" setzen
|
||||
if (!updateData.status) {
|
||||
updateData.status = 'Assigned'
|
||||
}
|
||||
} else if (!updateData.status) {
|
||||
// Keine Zuweisung mehr → Status auf "Open" setzen (nur wenn nicht explizit anders gesetzt)
|
||||
updateData.status = 'Open'
|
||||
}
|
||||
}
|
||||
|
||||
// Zuweisen aendert den Status nicht (frueher sprang er auf "Assigned")
|
||||
const response = await databases.updateDocument(
|
||||
DATABASE_ID,
|
||||
COLLECTIONS.WORKORDERS,
|
||||
id,
|
||||
updateData
|
||||
data
|
||||
)
|
||||
setWorkorders(prev =>
|
||||
prev.map(wo => wo.$id === id ? response : wo)
|
||||
|
||||
Reference in new issue
Block a user