This commit is contained in:
Basilosaurusrex committed 2025-12-29 22:28:43 +01:00
1 parent 7fb446c53a
commit 0e19df6895
73 files changed
+7907 -32290

No files matched your search

+158 -18
View File
@@ -5,11 +5,11 @@ const DEMO_MODE = !import.meta.env.VITE_APPWRITE_PROJECT_ID
// Demo data for testing without Appwrite
const DEMO_WORKORDERS = [
{ $id: '1', title: 'Server Wartung', description: 'Monatliche Wartung', status: 'Open', priority: 2, type: 'Maintenance', customerName: 'Kunde A', assignedName: 'Max M.', response: 'Onsite', $createdAt: new Date().toISOString() },
{ $id: '2', title: 'Netzwerk Problem', description: 'WLAN funktioniert nicht', status: 'Occupied', priority: 3, type: 'Support', customerName: 'Kunde B', assignedName: 'Lisa S.', response: 'Remote', $createdAt: new Date().toISOString() },
{ $id: '3', title: 'Software Installation', description: 'Office 365 Setup', status: 'Assigned', priority: 1, type: 'Installation', customerName: 'Kunde C', assignedName: 'Tom K.', response: 'Onsite', $createdAt: new Date().toISOString() },
{ $id: '4', title: 'Drucker defekt', description: 'Papierstau', status: 'Awaiting', priority: 2, type: 'Hardware', customerName: 'Kunde D', assignedName: '', response: 'Pickup', $createdAt: new Date().toISOString() },
{ $id: '5', title: 'Kritischer Serverausfall', description: 'Produktionsserver down', status: 'Open', priority: 4, type: 'Emergency', customerName: 'Kunde E', assignedName: 'Max M.', response: 'Onsite', $createdAt: new Date().toISOString() },
{ $id: '1', woid: '10001', title: 'Server Wartung', description: 'Monatliche Wartung', status: 'Open', priority: 2, type: 'Maintenance', customerName: 'Kunde A', assignedName: 'Max M.', response: 'Onsite', $createdAt: new Date().toISOString() },
{ $id: '2', woid: '10002', title: 'Netzwerk Problem', description: 'WLAN funktioniert nicht', status: 'Occupied', priority: 3, type: 'Support', customerName: 'Kunde B', assignedName: 'Lisa S.', response: 'Remote', $createdAt: new Date().toISOString() },
{ $id: '3', woid: '10003', title: 'Software Installation', description: 'Office 365 Setup', status: 'Assigned', priority: 1, type: 'Installation', customerName: 'Kunde C', assignedName: 'Tom K.', response: 'Onsite', $createdAt: new Date().toISOString() },
{ $id: '4', woid: '10004', title: 'Drucker defekt', description: 'Papierstau', status: 'Awaiting', priority: 2, type: 'Hardware', customerName: 'Kunde D', assignedName: '', response: 'Pickup', $createdAt: new Date().toISOString() },
{ $id: '5', woid: '10005', title: 'Kritischer Serverausfall', description: 'Produktionsserver down', status: 'Open', priority: 4, type: 'Emergency', customerName: 'Kunde E', assignedName: 'Max M.', response: 'Onsite', $createdAt: new Date().toISOString() },
]
export function useWorkorders(filters = {}) {
@@ -44,16 +44,27 @@ export function useWorkorders(filters = {}) {
queries.push(Query.limit(filters.limit))
}
// Für Arrays: In Appwrite 1.5.7 gibt es kein Query.or()
// Wir filtern clientseitig für mehrere Werte
if (filters.status && filters.status.length > 0) {
queries.push(Query.equal('status', filters.status))
if (filters.status.length === 1) {
queries.push(Query.equal('status', filters.status[0]))
}
// Für mehrere Werte: Clientseitig filtern (siehe unten)
}
if (filters.type && filters.type.length > 0) {
queries.push(Query.equal('type', filters.type))
if (filters.type.length === 1) {
queries.push(Query.equal('type', filters.type[0]))
}
// Für mehrere Werte: Clientseitig filtern
}
if (filters.priority && filters.priority.length > 0) {
queries.push(Query.equal('priority', filters.priority))
if (filters.priority.length === 1) {
queries.push(Query.equal('priority', filters.priority[0]))
}
// Für mehrere Werte: Clientseitig filtern
}
if (filters.customerId) {
@@ -64,16 +75,48 @@ export function useWorkorders(filters = {}) {
queries.push(Query.equal('assignedTo', filters.assignedTo))
}
// Debug: Zeige Collection ID
if (import.meta.env.DEV) {
console.log('📋 Fetching workorders:')
console.log(' Database ID:', DATABASE_ID)
console.log(' Collection ID:', COLLECTIONS.WORKORDERS)
console.log(' Queries:', queries.length)
}
const response = await databases.listDocuments(
DATABASE_ID,
COLLECTIONS.WORKORDERS,
queries
)
setWorkorders(response.documents)
// Clientseitige Filterung für Arrays (da Query.or() nicht verfügbar ist)
let filteredDocs = response.documents
if (filters.status && filters.status.length > 1) {
filteredDocs = filteredDocs.filter(doc => filters.status.includes(doc.status))
}
if (filters.type && filters.type.length > 1) {
filteredDocs = filteredDocs.filter(doc => filters.type.includes(doc.type))
}
if (filters.priority && filters.priority.length > 1) {
filteredDocs = filteredDocs.filter(doc => filters.priority.includes(doc.priority))
}
setWorkorders(filteredDocs)
setError(null)
} catch (err) {
setError(err.message)
let errorMessage = err.message || 'Fehler beim Laden der Tickets'
// Bessere Fehlermeldungen
if (err.code === 401 || errorMessage.includes('not authorized') || errorMessage.includes('Unauthorized')) {
errorMessage = 'Berechtigung fehlt: Bitte überprüfe die Read-Berechtigungen der Collection in Appwrite. Die Collection muss "Users" oder "Any" als Read-Berechtigung haben.'
} else if (errorMessage.includes('Collection') && errorMessage.includes('not found')) {
errorMessage = 'Collection nicht gefunden: Bitte überprüfe die Collection ID in der Konfiguration.'
}
setError(errorMessage)
console.error('Error fetching workorders:', err)
} finally {
setLoading(false)
@@ -86,26 +129,107 @@ export function useWorkorders(filters = {}) {
const createWorkorder = async (data) => {
if (DEMO_MODE) {
const newWo = { ...data, $id: Date.now().toString(), status: 'Open', $createdAt: new Date().toISOString() }
// Finde höchste WOID und +1
const maxWoid = workorders.length > 0
? Math.max(...workorders.map(wo => parseInt(wo.woid)).filter(w => !isNaN(w)))
: 9999;
const nextWoid = maxWoid + 1;
const newWo = { ...data, $id: Date.now().toString(), woid: nextWoid.toString(), status: 'Open', $createdAt: new Date().toISOString() }
setWorkorders(prev => [newWo, ...prev])
return { success: true, data: newWo }
}
try {
// Validierung: Prüfe required fields
if (!data.topic || data.topic.trim() === '') {
return { success: false, error: 'Das Feld "Topic" ist erforderlich.' }
}
// Status-Automatik: Wenn Mitarbeiter zugewiesen → Status = "Assigned", sonst "Open"
const autoStatus = (data.assignedTo && data.assignedTo !== '') ? 'Assigned' : 'Open'
// Generiere sequentielle 5-stellige WOID (wie im Original-System)
const generateWOID = () => {
// Finde die höchste bestehende WOID
if (workorders.length === 0) {
return '10000'; // Starte bei 10000 wenn keine Tickets existieren
}
const maxWoid = Math.max(
...workorders
.map(wo => parseInt(wo.woid))
.filter(woid => !isNaN(woid) && woid > 0)
);
// Wenn keine gültige WOID gefunden wurde, starte bei 10000
if (maxWoid === -Infinity || isNaN(maxWoid)) {
return '10000';
}
// Gib die nächste Nummer zurück (sequentiell)
return (maxWoid + 1).toString();
}
// Bereite Daten für Appwrite vor
const workorderData = {
// Required fields
topic: data.topic.trim(),
status: data.status || autoStatus, // Verwende übergebenen Status oder automatischen Status
priority: typeof data.priority === 'number' ? data.priority : parseInt(data.priority) || 1,
woid: generateWOID(), // 5-stellige Zahl
// Optional fields - nur senden wenn vorhanden
type: data.type || '',
systemType: data.systemType || '',
responseLevel: data.responseLevel || '',
serviceType: data.serviceType || 'Remote',
customerId: data.customerId || '',
assignedTo: data.assignedTo || '', // Zugewiesener Mitarbeiter
requestedBy: data.requestedBy || '',
requestedFor: data.requestedFor || '',
startDate: data.startDate || '',
startTime: data.startTime || '',
deadline: data.deadline || '',
endTime: data.endTime || '',
estimate: data.estimate || '',
mailCopyTo: data.mailCopyTo || '',
sendNotification: data.sendNotification || false,
details: data.details || '',
// Datetime field
createdAt: new Date().toISOString()
}
// Entferne leere Strings (außer für required fields)
Object.keys(workorderData).forEach(key => {
if (workorderData[key] === '' && key !== 'topic' && key !== 'status') {
delete workorderData[key]
}
})
console.log('Creating workorder with data:', workorderData)
const response = await databases.createDocument(
DATABASE_ID,
COLLECTIONS.WORKORDERS,
ID.unique(),
{
...data,
status: 'Open',
createdAt: new Date().toISOString()
}
workorderData
)
setWorkorders(prev => [response, ...prev])
return { success: true, data: response }
} catch (err) {
return { success: false, error: err.message }
console.error('Error creating workorder:', err)
let errorMessage = err.message || 'Fehler beim Erstellen des Tickets'
// Bessere Fehlermeldungen
if (err.code === 400 || errorMessage.includes('Bad Request')) {
errorMessage = 'Ungültige Daten: Bitte überprüfe, ob alle Pflichtfelder ausgefüllt sind und die Daten korrekt sind. Details: ' + (err.message || 'Unbekannter Fehler')
} else if (errorMessage.includes('required') || errorMessage.includes('missing')) {
errorMessage = 'Pflichtfelder fehlen: Bitte fülle alle erforderlichen Felder aus.'
}
return { success: false, error: errorMessage }
}
}
@@ -116,11 +240,27 @@ export function useWorkorders(filters = {}) {
}
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'
}
}
const response = await databases.updateDocument(
DATABASE_ID,
COLLECTIONS.WORKORDERS,
id,
data
updateData
)
setWorkorders(prev =>
prev.map(wo => wo.$id === id ? response : wo)