Finanzen nur noch anzeigen, Dashboard und Admin-Konfiguration entfernt (Paket D)
- Finanzen: Liste, Zahlen, PDF und Link zu InvoiceNinja bleiben. Das Formular "Rechnung erstellen" (auf der Seite und als "Rechnung aus Ticket erstellen" im Ticket) ist weg; Rechnungen entstehen direkt in InvoiceNinja. Das Verknüpfen von Kunden mit InvoiceNinja bleibt. - Filter "Bezahlt" repariert: InvoiceNinja liefert status_id als Text. - FinancePage.jsx und InvoicePanel.jsx waren Windows-1252 kodiert und zeigten live "�"; jetzt UTF-8, dazu Umlaute in den Texten. - Dashboard entfernt (doppelte Finanzzahlen, "Offen" zählte falsch); alte Links führen zu den Tickets. - Admin: Reiter "Konfiguration" (nur noch Prioritäten, die seit Paket B niemand liest) mit useAdminConfig entfernt; Admin startet bei Kunden. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
34c4db0228
commit
1a8604f7e6
12 files changed
+40
-617
No files matched your search
@@ -1,156 +0,0 @@
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
import { databases, DATABASE_ID, COLLECTIONS, ID } from '../lib/appwrite'
|
||||
|
||||
// Standardwerte, solange das Config-Dokument fehlt oder nicht lesbar ist
|
||||
const DEFAULT_CONFIG = {
|
||||
ticketTypes: [
|
||||
'Home Office', 'Holidays', 'Trip', 'Supportrequest', 'Change Request',
|
||||
'Maintenance', 'Project', 'Webpage', 'Controlling', 'Development', 'Documentation',
|
||||
'Meeting/Conference', 'IT Management', 'IT Security', 'Procurement',
|
||||
'Rollout', 'Emergency Call', 'Other Services'
|
||||
],
|
||||
systems: [
|
||||
'Account View', 'Client', 'Cofano', 'Credentials', 'Diamant', 'Docuware',
|
||||
'EDI', 'eMail', 'Employee', 'Invoice', 'LBase', 'Medical Office', 'Network',
|
||||
'O365', 'PDF Viewer', 'Printer', 'Reports', 'Server', 'Time Tracking',
|
||||
'TK', 'TOS', 'Vivendi NG', 'VGM', '(W)LAN', '(W)WAN', 'WOMS', 'n/a'
|
||||
],
|
||||
responseLevels: [
|
||||
'USER', 'KEY USER', 'Helpdesk', 'Support', 'Admin', 'FS/FE', '24/7',
|
||||
'TECH MGMT', 'Backoffice', 'BUSI MGMT', 'n/a'
|
||||
],
|
||||
serviceTypes: ['Remote', 'On Site', 'Off Site'],
|
||||
priorities: [
|
||||
{ value: 0, label: 'None' },
|
||||
{ value: 1, label: 'Low' },
|
||||
{ value: 2, label: 'Medium' },
|
||||
{ value: 3, label: 'High' },
|
||||
{ value: 4, label: 'Critical' }
|
||||
]
|
||||
}
|
||||
|
||||
function normalizePriorities(values) {
|
||||
if (!Array.isArray(values)) return DEFAULT_CONFIG.priorities
|
||||
const parsed = values.map((item, index) => {
|
||||
if (typeof item === 'object' && item !== null) return item
|
||||
if (typeof item === 'string') {
|
||||
try {
|
||||
const value = JSON.parse(item)
|
||||
if (value && typeof value === 'object') return value
|
||||
} catch {
|
||||
return { value: index, label: item }
|
||||
}
|
||||
}
|
||||
return null
|
||||
}).filter(Boolean)
|
||||
return parsed.length > 0 ? parsed : DEFAULT_CONFIG.priorities
|
||||
}
|
||||
|
||||
export function useAdminConfig() {
|
||||
const [config, setConfig] = useState(DEFAULT_CONFIG)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [error, setError] = useState(null)
|
||||
|
||||
const fetchConfig = useCallback(async () => {
|
||||
try {
|
||||
// Versuche Config-Dokument zu laden (ID: 'config')
|
||||
try {
|
||||
const doc = await databases.getDocument(
|
||||
DATABASE_ID,
|
||||
COLLECTIONS.CONFIG || 'config',
|
||||
'config'
|
||||
)
|
||||
setConfig({
|
||||
ticketTypes: doc.ticketTypes || DEFAULT_CONFIG.ticketTypes,
|
||||
systems: doc.systems || DEFAULT_CONFIG.systems,
|
||||
responseLevels: doc.responseLevels || DEFAULT_CONFIG.responseLevels,
|
||||
serviceTypes: doc.serviceTypes || DEFAULT_CONFIG.serviceTypes,
|
||||
priorities: normalizePriorities(doc.priorities)
|
||||
})
|
||||
} catch (e) {
|
||||
// Config existiert noch nicht (404) - das ist normal, verwende Defaults
|
||||
if (e.code === 404 || e.message?.includes('not found')) {
|
||||
setConfig(DEFAULT_CONFIG)
|
||||
setError(null) // Kein Fehler, Collection existiert einfach noch nicht
|
||||
} else {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
setError(null)
|
||||
} catch (err) {
|
||||
console.error('Error fetching config:', err)
|
||||
// Nur echte Fehler als Error setzen, nicht 404
|
||||
if (err.code !== 404 && !err.message?.includes('not found')) {
|
||||
setError(err.message)
|
||||
} else {
|
||||
setError(null)
|
||||
}
|
||||
setConfig(DEFAULT_CONFIG) // Fallback zu Defaults
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
fetchConfig()
|
||||
}, [fetchConfig])
|
||||
|
||||
const updateConfig = async (newConfig) => {
|
||||
try {
|
||||
const configData = {
|
||||
ticketTypes: newConfig.ticketTypes,
|
||||
systems: newConfig.systems,
|
||||
responseLevels: newConfig.responseLevels,
|
||||
serviceTypes: newConfig.serviceTypes,
|
||||
priorities: normalizePriorities(newConfig.priorities).map((priority) =>
|
||||
JSON.stringify(priority)
|
||||
)
|
||||
}
|
||||
|
||||
try {
|
||||
// Versuche zu aktualisieren
|
||||
await databases.updateDocument(
|
||||
DATABASE_ID,
|
||||
COLLECTIONS.CONFIG || 'config',
|
||||
'config',
|
||||
configData
|
||||
)
|
||||
} catch (e) {
|
||||
// Dokument existiert nicht (404) oder Collection existiert nicht
|
||||
if (e.code === 404 || e.message?.includes('not found')) {
|
||||
// Versuche zu erstellen
|
||||
try {
|
||||
await databases.createDocument(
|
||||
DATABASE_ID,
|
||||
COLLECTIONS.CONFIG || 'config',
|
||||
'config',
|
||||
configData
|
||||
)
|
||||
} catch (createErr) {
|
||||
// Collection existiert nicht - zeige hilfreiche Fehlermeldung
|
||||
if (createErr.code === 404 || createErr.message?.includes('Collection')) {
|
||||
throw new Error('Die "config" Collection existiert noch nicht. Bitte erstelle sie zuerst in Appwrite.')
|
||||
}
|
||||
throw createErr
|
||||
}
|
||||
} else {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
setConfig(newConfig)
|
||||
return { success: true }
|
||||
} catch (err) {
|
||||
console.error('Error updating config:', err)
|
||||
return { success: false, error: err.message }
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
config,
|
||||
loading,
|
||||
error,
|
||||
updateConfig,
|
||||
refresh: fetchConfig
|
||||
}
|
||||
}
|
||||
@@ -32,18 +32,5 @@ export function useInvoices(clientId) {
|
||||
fetchInvoices()
|
||||
}, [fetchInvoices])
|
||||
|
||||
const createInvoice = useCallback(
|
||||
async (payload) => {
|
||||
try {
|
||||
const data = await integrationsApi.createInvoice(payload)
|
||||
await fetchInvoices()
|
||||
return { success: true, invoice: data.invoice }
|
||||
} catch (err) {
|
||||
return { success: false, error: err.message }
|
||||
}
|
||||
},
|
||||
[fetchInvoices]
|
||||
)
|
||||
|
||||
return { invoices, loading, error, refresh: fetchInvoices, createInvoice }
|
||||
return { invoices, loading, error, refresh: fetchInvoices }
|
||||
}
|
||||
Reference in new issue
Block a user