Demo-Modus entfernt
isDemoMode war nie aktiv: appwrite.js hat immer eine Projekt-ID als Fallback. Weg sind die Demo-Zweige in Anmeldung und Hooks sowie die Beispieldaten aus der alten IT-Welt (Serverausfall, Drucker, Kunde A–E). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
889a2f42eb
commit
b758b1f9a7
11 files changed
+25
-451
No files matched your search
@@ -2,7 +2,7 @@ import { useState, useEffect, useMemo } from 'react'
|
||||
import { FaTimes } from 'react-icons/fa'
|
||||
import { useAdminConfig } from '../hooks/useAdminConfig'
|
||||
import { useEmployees } from '../hooks/useEmployees'
|
||||
import { databases, DATABASE_ID, COLLECTIONS, Query, isDemoMode } from '../lib/appwrite'
|
||||
import { databases, DATABASE_ID, COLLECTIONS, Query } from '../lib/appwrite'
|
||||
import {
|
||||
SERVICE_TYPES,
|
||||
todayIso,
|
||||
@@ -63,7 +63,7 @@ export default function CreateTicketModal({ isOpen, onClose, onCreate, customers
|
||||
|
||||
// Namen aus den letzten Tickets fuer die Autovervollstaendigung
|
||||
useEffect(() => {
|
||||
if (!isOpen || isDemoMode) return
|
||||
if (!isOpen) return
|
||||
let cancelled = false
|
||||
databases
|
||||
.listDocuments(DATABASE_ID, COLLECTIONS.WORKORDERS, [Query.orderDesc('$createdAt'), Query.limit(200)])
|
||||
|
||||
@@ -7,14 +7,11 @@ import {
|
||||
ID,
|
||||
Query,
|
||||
hasAppwriteSession,
|
||||
isDemoMode,
|
||||
projectId as PROJECT_ID,
|
||||
} from '../lib/appwrite'
|
||||
|
||||
const AuthContext = createContext()
|
||||
|
||||
const DEMO_MODE = isDemoMode
|
||||
|
||||
function clearStaleAppwriteSessions() {
|
||||
if (typeof window === 'undefined' || !window.localStorage) return
|
||||
try {
|
||||
@@ -55,7 +52,7 @@ async function createSessionWithCleanup(email, password) {
|
||||
// Hilfsfunktion: Fügt User automatisch zur employees Collection hinzu und liefert
|
||||
// den Mitarbeiter-Eintrag (Kürzel = Gitea-Name, siehe isWorksheetCreator) oder null
|
||||
async function ensureEmployeeExists(user) {
|
||||
if (!user || DEMO_MODE) return null
|
||||
if (!user) return null
|
||||
|
||||
try {
|
||||
const response = await databases.listDocuments(
|
||||
@@ -98,15 +95,6 @@ export function AuthProvider({ children }) {
|
||||
}, [])
|
||||
|
||||
async function checkUser() {
|
||||
if (DEMO_MODE) {
|
||||
const demoUser = localStorage.getItem('demo_user')
|
||||
if (demoUser) {
|
||||
setUser(JSON.parse(demoUser))
|
||||
}
|
||||
setLoading(false)
|
||||
return
|
||||
}
|
||||
|
||||
if (!hasAppwriteSession()) {
|
||||
setUser(null)
|
||||
setLoading(false)
|
||||
@@ -131,13 +119,6 @@ export function AuthProvider({ children }) {
|
||||
}
|
||||
|
||||
async function login(email, password) {
|
||||
if (DEMO_MODE) {
|
||||
const demoUser = { $id: 'demo', email, name: email.split('@')[0] }
|
||||
localStorage.setItem('demo_user', JSON.stringify(demoUser))
|
||||
setUser(demoUser)
|
||||
return { success: true }
|
||||
}
|
||||
|
||||
try {
|
||||
const normalizedEmail = email.trim()
|
||||
const normalizedPassword = password.trim()
|
||||
@@ -176,12 +157,6 @@ export function AuthProvider({ children }) {
|
||||
}
|
||||
|
||||
async function logout() {
|
||||
if (DEMO_MODE) {
|
||||
localStorage.removeItem('demo_user')
|
||||
setUser(null)
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await account.deleteSessions()
|
||||
} catch (error) {
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
import { databases, DATABASE_ID, COLLECTIONS, ID, isDemoMode } from '../lib/appwrite'
|
||||
import { databases, DATABASE_ID, COLLECTIONS, ID } from '../lib/appwrite'
|
||||
|
||||
const DEMO_MODE = isDemoMode
|
||||
|
||||
// Default-Werte für Demo-Modus
|
||||
// Standardwerte, solange das Config-Dokument fehlt oder nicht lesbar ist
|
||||
const DEFAULT_CONFIG = {
|
||||
ticketTypes: [
|
||||
'Home Office', 'Holidays', 'Trip', 'Supportrequest', 'Change Request',
|
||||
@@ -54,12 +52,6 @@ export function useAdminConfig() {
|
||||
const [error, setError] = useState(null)
|
||||
|
||||
const fetchConfig = useCallback(async () => {
|
||||
if (DEMO_MODE) {
|
||||
setConfig(DEFAULT_CONFIG)
|
||||
setLoading(false)
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
// Versuche Config-Dokument zu laden (ID: 'config')
|
||||
try {
|
||||
@@ -104,12 +96,6 @@ export function useAdminConfig() {
|
||||
}, [fetchConfig])
|
||||
|
||||
const updateConfig = async (newConfig) => {
|
||||
if (DEMO_MODE) {
|
||||
setConfig(newConfig)
|
||||
localStorage.setItem('admin_config', JSON.stringify(newConfig))
|
||||
return { success: true }
|
||||
}
|
||||
|
||||
try {
|
||||
const configData = {
|
||||
ticketTypes: newConfig.ticketTypes,
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
DATABASE_ID,
|
||||
Query,
|
||||
databases,
|
||||
isDemoMode,
|
||||
} from '../lib/appwrite'
|
||||
import {
|
||||
createCustomerWithPortalAccess,
|
||||
@@ -13,26 +12,12 @@ import {
|
||||
updateCustomerWithPortalAccess,
|
||||
} from '../lib/customerAdminApi'
|
||||
|
||||
const DEMO_MODE = isDemoMode
|
||||
|
||||
// Demo-Kunden für Testing
|
||||
const DEMO_CUSTOMERS = [
|
||||
{ $id: '1', code: 'C001', name: 'Kunde A', location: 'Berlin', email: 'kunde.a@example.com', phone: '030-123456' },
|
||||
{ $id: '2', code: 'C002', name: 'Kunde B', location: 'München', email: 'kunde.b@example.com', phone: '089-654321' }
|
||||
]
|
||||
|
||||
export function useCustomers() {
|
||||
const [customers, setCustomers] = useState([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [error, setError] = useState(null)
|
||||
|
||||
const fetchCustomers = useCallback(async () => {
|
||||
if (DEMO_MODE) {
|
||||
setCustomers(DEMO_CUSTOMERS)
|
||||
setLoading(false)
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
try {
|
||||
const response = await listCustomersForAdmin()
|
||||
@@ -67,17 +52,6 @@ export function useCustomers() {
|
||||
}, [fetchCustomers])
|
||||
|
||||
const createCustomer = async (data) => {
|
||||
if (DEMO_MODE) {
|
||||
const { password, ...rest } = data
|
||||
const newCustomer = {
|
||||
...rest,
|
||||
portalPassword: password || rest.portalPassword || '',
|
||||
$id: Date.now().toString(),
|
||||
}
|
||||
setCustomers(prev => [...prev, newCustomer])
|
||||
return { success: true, data: newCustomer }
|
||||
}
|
||||
|
||||
try {
|
||||
const { password, ...fields } = data
|
||||
const result = await createCustomerWithPortalAccess({ ...fields, password })
|
||||
@@ -93,19 +67,6 @@ export function useCustomers() {
|
||||
}
|
||||
|
||||
const updateCustomer = async (id, data) => {
|
||||
if (DEMO_MODE) {
|
||||
const { password, ...rest } = data
|
||||
setCustomers(prev =>
|
||||
prev.map(c => {
|
||||
if (c.$id !== id) return c
|
||||
const next = { ...c, ...rest }
|
||||
if (password) next.portalPassword = password
|
||||
return next
|
||||
})
|
||||
)
|
||||
return { success: true }
|
||||
}
|
||||
|
||||
try {
|
||||
const { password, ...fields } = data
|
||||
const payload = { ...fields }
|
||||
@@ -135,11 +96,6 @@ export function useCustomers() {
|
||||
}
|
||||
|
||||
const deleteCustomer = async (id) => {
|
||||
if (DEMO_MODE) {
|
||||
setCustomers(prev => prev.filter(c => c.$id !== id))
|
||||
return { success: true }
|
||||
}
|
||||
|
||||
try {
|
||||
await deleteCustomerWithPortalAccess(id)
|
||||
setCustomers(prev => prev.filter(c => c.$id !== id))
|
||||
|
||||
+11
-51
@@ -4,7 +4,6 @@ import {
|
||||
DATABASE_ID,
|
||||
Query,
|
||||
databases,
|
||||
isDemoMode,
|
||||
} from '../lib/appwrite'
|
||||
import {
|
||||
createEmployeeWithLogin,
|
||||
@@ -13,26 +12,6 @@ import {
|
||||
updateEmployeeWithLogin,
|
||||
} from '../lib/employeeAdminApi'
|
||||
|
||||
const DEMO_MODE = isDemoMode
|
||||
const DEMO_EMPLOYEES = [
|
||||
{
|
||||
$id: '1',
|
||||
userId: 'user1',
|
||||
displayName: 'Kenso Grimm',
|
||||
email: 'kenso@example.com',
|
||||
shortcode: 'KNSO',
|
||||
isAdmin: true,
|
||||
},
|
||||
{
|
||||
$id: '2',
|
||||
userId: 'user2',
|
||||
displayName: 'Christian Lehmann',
|
||||
email: 'christian@example.com',
|
||||
shortcode: 'CHLE',
|
||||
isAdmin: false,
|
||||
},
|
||||
]
|
||||
|
||||
export function useEmployees() {
|
||||
const [employees, setEmployees] = useState([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
@@ -41,20 +20,16 @@ export function useEmployees() {
|
||||
const fetchEmployees = useCallback(async () => {
|
||||
setLoading(true)
|
||||
try {
|
||||
if (DEMO_MODE) {
|
||||
setEmployees(DEMO_EMPLOYEES)
|
||||
} else {
|
||||
try {
|
||||
const result = await listEmployeesForAdmin()
|
||||
setEmployees(result.employees || [])
|
||||
} catch {
|
||||
const result = await databases.listDocuments(
|
||||
DATABASE_ID,
|
||||
COLLECTIONS.EMPLOYEES,
|
||||
[Query.orderAsc('displayName')]
|
||||
)
|
||||
setEmployees(result.documents || [])
|
||||
}
|
||||
try {
|
||||
const result = await listEmployeesForAdmin()
|
||||
setEmployees(result.employees || [])
|
||||
} catch {
|
||||
const result = await databases.listDocuments(
|
||||
DATABASE_ID,
|
||||
COLLECTIONS.EMPLOYEES,
|
||||
[Query.orderAsc('displayName')]
|
||||
)
|
||||
setEmployees(result.documents || [])
|
||||
}
|
||||
setError(null)
|
||||
} catch (err) {
|
||||
@@ -71,15 +46,6 @@ export function useEmployees() {
|
||||
|
||||
const createEmployee = async (data) => {
|
||||
try {
|
||||
if (DEMO_MODE) {
|
||||
const employee = {
|
||||
...data,
|
||||
userId: crypto.randomUUID(),
|
||||
$id: Date.now().toString(),
|
||||
}
|
||||
setEmployees((current) => [...current, employee])
|
||||
return { success: true, data: employee }
|
||||
}
|
||||
const result = await createEmployeeWithLogin(data)
|
||||
setEmployees((current) => [...current, result.employee])
|
||||
return { success: true, data: result.employee }
|
||||
@@ -90,12 +56,6 @@ export function useEmployees() {
|
||||
|
||||
const updateEmployee = async (id, data) => {
|
||||
try {
|
||||
if (DEMO_MODE) {
|
||||
setEmployees((current) =>
|
||||
current.map((employee) => employee.$id === id ? { ...employee, ...data } : employee)
|
||||
)
|
||||
return { success: true }
|
||||
}
|
||||
const result = await updateEmployeeWithLogin(id, data)
|
||||
setEmployees((current) =>
|
||||
current.map((employee) => employee.$id === id ? result.employee : employee)
|
||||
@@ -108,7 +68,7 @@ export function useEmployees() {
|
||||
|
||||
const deleteEmployee = async (id) => {
|
||||
try {
|
||||
if (!DEMO_MODE) await deleteEmployeeWithLogin(id)
|
||||
await deleteEmployeeWithLogin(id)
|
||||
setEmployees((current) => current.filter((employee) => employee.$id !== id))
|
||||
return { success: true }
|
||||
} catch (err) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState, useCallback } from 'react'
|
||||
import { databases, DATABASE_ID, COLLECTIONS, ID, isDemoMode } from '../lib/appwrite'
|
||||
import { databases, DATABASE_ID, COLLECTIONS, ID } from '../lib/appwrite'
|
||||
import {
|
||||
fetchRoadmapNodes,
|
||||
logNodeStatusWorksheet,
|
||||
@@ -14,7 +14,7 @@ export function useRoadmapNodes() {
|
||||
const [error, setError] = useState(null)
|
||||
|
||||
const fetchNodes = useCallback(async (roadmapId) => {
|
||||
if (!roadmapId || isDemoMode) return []
|
||||
if (!roadmapId) return []
|
||||
setLoading(true)
|
||||
setError(null)
|
||||
try {
|
||||
@@ -30,7 +30,6 @@ export function useRoadmapNodes() {
|
||||
}, [])
|
||||
|
||||
const createNode = async (roadmapId, { title, column, row, kind }) => {
|
||||
if (isDemoMode) return { success: false, error: 'Demo-Modus' }
|
||||
try {
|
||||
const now = new Date().toISOString()
|
||||
const doc = await databases.createDocument(DATABASE_ID, COLLECTIONS.ROADMAP_NODES, ID.unique(), {
|
||||
@@ -51,7 +50,6 @@ export function useRoadmapNodes() {
|
||||
}
|
||||
|
||||
const updateNode = async (nodeId, data) => {
|
||||
if (isDemoMode) return { success: false, error: 'Demo-Modus' }
|
||||
try {
|
||||
const doc = await databases.updateDocument(DATABASE_ID, COLLECTIONS.ROADMAP_NODES, nodeId, {
|
||||
...data,
|
||||
@@ -66,7 +64,6 @@ export function useRoadmapNodes() {
|
||||
|
||||
/** Knoten loeschen inkl. Bereinigung eingehender Kanten bei den Nachfolgern. */
|
||||
const deleteNode = async (node) => {
|
||||
if (isDemoMode) return { success: false, error: 'Demo-Modus' }
|
||||
if (node.kind === NODE_KIND.START) {
|
||||
return { success: false, error: 'Der Start-Knoten kann nicht geloescht werden.' }
|
||||
}
|
||||
@@ -96,7 +93,6 @@ export function useRoadmapNodes() {
|
||||
|
||||
/** Kante anlegen: immer vorwaerts (Zielspalte > Quellspalte), keine Duplikate. */
|
||||
const connectNodes = async (source, target) => {
|
||||
if (isDemoMode) return { success: false, error: 'Demo-Modus' }
|
||||
if (source.$id === target.$id) return { success: false, error: 'Knoten kann nicht mit sich selbst verbunden werden.' }
|
||||
if (target.column <= source.column) {
|
||||
return { success: false, error: 'Verbindungen laufen immer vorwaerts (nach rechts).' }
|
||||
@@ -113,7 +109,6 @@ export function useRoadmapNodes() {
|
||||
|
||||
/** Statuswechsel inkl. Worksheet-Log am Projektticket; meldet, ob alle Ziele fertig sind. */
|
||||
const setNodeStatus = async (roadmap, node, newStatus, user) => {
|
||||
if (isDemoMode) return { success: false, error: 'Demo-Modus' }
|
||||
const oldStatus = node.status || NODE_STATUS.OPEN
|
||||
if (oldStatus === newStatus) return { success: true, allGoalsDone: false }
|
||||
const result = await updateNode(node.$id, { status: newStatus })
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState, useCallback } from 'react'
|
||||
import { databases, DATABASE_ID, COLLECTIONS, Query, isDemoMode } from '../lib/appwrite'
|
||||
import { databases, DATABASE_ID, COLLECTIONS, Query } from '../lib/appwrite'
|
||||
import {
|
||||
createRoadmapPlan,
|
||||
deleteRoadmapPlan,
|
||||
@@ -13,7 +13,6 @@ export function useRoadmaps() {
|
||||
const [error, setError] = useState(null)
|
||||
|
||||
const fetchAll = useCallback(async () => {
|
||||
if (isDemoMode) return []
|
||||
setLoading(true)
|
||||
setError(null)
|
||||
try {
|
||||
@@ -32,7 +31,7 @@ export function useRoadmaps() {
|
||||
}, [])
|
||||
|
||||
const fetchById = useCallback(async (roadmapId) => {
|
||||
if (!roadmapId || isDemoMode) return null
|
||||
if (!roadmapId) return null
|
||||
try {
|
||||
return await databases.getDocument(DATABASE_ID, COLLECTIONS.ROADMAPS, roadmapId)
|
||||
} catch {
|
||||
@@ -41,7 +40,6 @@ export function useRoadmaps() {
|
||||
}, [])
|
||||
|
||||
const fetchByTicketId = useCallback(async (ticketId) => {
|
||||
if (isDemoMode) return null
|
||||
try {
|
||||
return await fetchRoadmapByTicketId(ticketId)
|
||||
} catch {
|
||||
@@ -50,7 +48,6 @@ export function useRoadmaps() {
|
||||
}, [])
|
||||
|
||||
const createRoadmap = async (project, data, user) => {
|
||||
if (isDemoMode) return { success: false, error: 'Demo-Modus' }
|
||||
try {
|
||||
const result = await createRoadmapPlan(project, data, user)
|
||||
setRoadmaps((prev) => [result.roadmap, ...prev])
|
||||
@@ -61,7 +58,6 @@ export function useRoadmaps() {
|
||||
}
|
||||
|
||||
const updateRoadmap = async (roadmapId, data) => {
|
||||
if (isDemoMode) return { success: false, error: 'Demo-Modus' }
|
||||
try {
|
||||
const doc = await databases.updateDocument(DATABASE_ID, COLLECTIONS.ROADMAPS, roadmapId, {
|
||||
...data,
|
||||
@@ -75,7 +71,6 @@ export function useRoadmaps() {
|
||||
}
|
||||
|
||||
const deleteRoadmap = async (roadmap, user) => {
|
||||
if (isDemoMode) return { success: false, error: 'Demo-Modus' }
|
||||
try {
|
||||
await deleteRoadmapPlan(roadmap, user)
|
||||
setRoadmaps((prev) => prev.filter((r) => r.$id !== roadmap.$id))
|
||||
@@ -86,7 +81,6 @@ export function useRoadmaps() {
|
||||
}
|
||||
|
||||
const completePlan = async (roadmap, user) => {
|
||||
if (isDemoMode) return { success: false, error: 'Demo-Modus' }
|
||||
try {
|
||||
const updated = await completeRoadmap(roadmap, user)
|
||||
setRoadmaps((prev) => prev.map((r) => (r.$id === updated.$id ? updated : r)))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState, useCallback } from 'react'
|
||||
import { databases, DATABASE_ID, COLLECTIONS, Query, isDemoMode } from '../lib/appwrite'
|
||||
import { databases, DATABASE_ID, COLLECTIONS, Query } from '../lib/appwrite'
|
||||
|
||||
export function useWebsiteProjects() {
|
||||
const [projects, setProjects] = useState([])
|
||||
@@ -7,7 +7,6 @@ export function useWebsiteProjects() {
|
||||
const [error, setError] = useState(null)
|
||||
|
||||
const fetchAllProjects = useCallback(async () => {
|
||||
if (isDemoMode) return []
|
||||
setLoading(true)
|
||||
setError(null)
|
||||
try {
|
||||
@@ -26,7 +25,7 @@ export function useWebsiteProjects() {
|
||||
}, [])
|
||||
|
||||
const fetchByTicketId = useCallback(async (ticketId) => {
|
||||
if (!ticketId || isDemoMode) return []
|
||||
if (!ticketId) return []
|
||||
try {
|
||||
const response = await databases.listDocuments(
|
||||
DATABASE_ID, COLLECTIONS.WEBSITE_PROJECTS,
|
||||
|
||||
+2
-108
@@ -1,7 +1,5 @@
|
||||
import { useState, useEffect, useCallback, useMemo } from 'react'
|
||||
import { databases, DATABASE_ID, COLLECTIONS, Query, ID, isDemoMode } from '../lib/appwrite'
|
||||
|
||||
const DEMO_MODE = isDemoMode
|
||||
import { databases, DATABASE_ID, COLLECTIONS, Query, ID } from '../lib/appwrite'
|
||||
|
||||
function buildFiltersKey(filters = {}) {
|
||||
return JSON.stringify({
|
||||
@@ -15,68 +13,6 @@ function buildFiltersKey(filters = {}) {
|
||||
})
|
||||
}
|
||||
|
||||
// Demo data for testing without Appwrite
|
||||
const lastWeek = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)
|
||||
|
||||
const DEMO_WORKORDERS = [
|
||||
{
|
||||
$id: 'dummy-10001',
|
||||
woid: '10001',
|
||||
topic: 'Kompletter Systemausfall - Server & Netzwerk',
|
||||
status: 'Assigned',
|
||||
priority: 4,
|
||||
type: 'Emergency Call',
|
||||
systemType: 'Server',
|
||||
responseLevel: 'Backoffice',
|
||||
serviceType: 'On Site',
|
||||
customerName: 'Kunde A',
|
||||
customerLocation: 'Hauptstraße 123, 12345 Musterstadt',
|
||||
assignedTo: 'user-max-id',
|
||||
assignedName: 'Max Mustermann',
|
||||
requestedBy: 'Dr. Anna Schmidt',
|
||||
requestedFor: 'IT-Abteilung Kunde A',
|
||||
startDate: '30.12.2025',
|
||||
startTime: '0800',
|
||||
deadline: '31.12.2025',
|
||||
endTime: '1800',
|
||||
estimate: '480',
|
||||
mailCopyTo: 'admin@kunde-a.de, it@kunde-a.de',
|
||||
sendNotification: true,
|
||||
details: `KRITISCHER SYSTEMAUSFALL - SOFORTIGE BEARBEITUNG ERFORDERLICH
|
||||
|
||||
Problembeschreibung:
|
||||
- Kompletter Serverausfall im Rechenzentrum
|
||||
- Alle Server sind offline (keine Verbindung möglich)
|
||||
- Netzwerk-Infrastruktur betroffen
|
||||
- Keine Backup-Systeme verfügbar
|
||||
|
||||
Betroffene Systeme:
|
||||
- Hauptserver (Windows Server 2022)
|
||||
- Datenbankserver (SQL Server 2019)
|
||||
- Fileserver
|
||||
- Exchange Server
|
||||
- Netzwerk-Switches
|
||||
|
||||
Auswirkungen:
|
||||
- Keine E-Mail-Kommunikation möglich
|
||||
- Alle Anwendungen offline
|
||||
- Kein Zugriff auf Datenbanken
|
||||
- Produktion steht still
|
||||
|
||||
Dringlichkeit: KRITISCH - Produktionsausfall
|
||||
|
||||
Erwartete Bearbeitungszeit: 8 Stunden
|
||||
Benötigte Ressourcen: 2 Techniker, Hardware-Ersatzteile`,
|
||||
approvalStatus: 'approved',
|
||||
$createdAt: lastWeek.toISOString(),
|
||||
createdAt: lastWeek.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 = {}) {
|
||||
const [workorders, setWorkorders] = useState([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
@@ -94,27 +30,7 @@ export function useWorkorders(filters = {}) {
|
||||
const fetchWorkorders = useCallback(async () => {
|
||||
const activeFilters = JSON.parse(filtersKey)
|
||||
setLoading(true)
|
||||
|
||||
if (DEMO_MODE) {
|
||||
// Filter demo data
|
||||
let filtered = [...DEMO_WORKORDERS]
|
||||
if (activeFilters.status?.length > 0) {
|
||||
filtered = filtered.filter(wo => activeFilters.status.includes(wo.status))
|
||||
}
|
||||
if (activeFilters.priority?.length > 0) {
|
||||
filtered = filtered.filter(wo => activeFilters.priority.includes(wo.priority))
|
||||
}
|
||||
if (activeFilters.woid) {
|
||||
filtered = filtered.filter(wo => String(wo.woid) === String(activeFilters.woid))
|
||||
}
|
||||
if (activeFilters.limit) {
|
||||
filtered = filtered.slice(0, activeFilters.limit)
|
||||
}
|
||||
setWorkorders(filtered)
|
||||
setLoading(false)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
const queries = [Query.orderDesc('$createdAt')]
|
||||
|
||||
@@ -236,18 +152,6 @@ export function useWorkorders(filters = {}) {
|
||||
}
|
||||
|
||||
const createWorkorder = async (data) => {
|
||||
if (DEMO_MODE) {
|
||||
// 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() === '') {
|
||||
@@ -323,11 +227,6 @@ export function useWorkorders(filters = {}) {
|
||||
}
|
||||
|
||||
const updateWorkorder = async (id, data) => {
|
||||
if (DEMO_MODE) {
|
||||
setWorkorders(prev => prev.map(wo => wo.$id === id ? { ...wo, ...data } : wo))
|
||||
return { success: true }
|
||||
}
|
||||
|
||||
try {
|
||||
// Status-Automatik beim Update:
|
||||
// Wenn assignedTo gesetzt wird → Status = "Assigned"
|
||||
@@ -361,11 +260,6 @@ export function useWorkorders(filters = {}) {
|
||||
}
|
||||
|
||||
const deleteWorkorder = async (id) => {
|
||||
if (DEMO_MODE) {
|
||||
setWorkorders(prev => prev.filter(wo => wo.$id !== id))
|
||||
return { success: true }
|
||||
}
|
||||
|
||||
try {
|
||||
await databases.deleteDocument(
|
||||
DATABASE_ID,
|
||||
|
||||
+1
-182
@@ -1,149 +1,7 @@
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
import { databases, DATABASE_ID, COLLECTIONS, Query, ID, isDemoMode } from '../lib/appwrite'
|
||||
import { databases, DATABASE_ID, COLLECTIONS, Query, ID } from '../lib/appwrite'
|
||||
import { canEditWorksheetTimes, isGitWorksheet } from '../lib/ticketForm'
|
||||
|
||||
const DEMO_MODE = isDemoMode
|
||||
|
||||
// Demo data für Testing - Vollständiges Dummy-Ticket 10001 mit allen Worksheets
|
||||
const yesterday = new Date(Date.now() - 24 * 60 * 60 * 1000)
|
||||
const twoDaysAgo = new Date(Date.now() - 48 * 60 * 60 * 1000)
|
||||
const threeDaysAgo = new Date(Date.now() - 72 * 60 * 60 * 1000)
|
||||
|
||||
const DEMO_WORKSHEETS = [
|
||||
{
|
||||
$id: 'ws-10001-001',
|
||||
wsid: '100001',
|
||||
woid: '10001',
|
||||
workorderId: 'dummy-10001',
|
||||
employeeId: 'user-max-id',
|
||||
employeeName: 'Max Mustermann',
|
||||
employeeShort: 'MM',
|
||||
serviceType: 'Remote',
|
||||
oldStatus: 'Open',
|
||||
newStatus: 'Occupied',
|
||||
oldResponseLevel: '',
|
||||
newResponseLevel: '24/7',
|
||||
totalTime: 30,
|
||||
startDate: '23.12.2025',
|
||||
startTime: '0800',
|
||||
endDate: '23.12.2025',
|
||||
endTime: '0830',
|
||||
details: 'Erste Analyse durchgeführt. Server komplett offline. Keine Remote-Verbindung möglich. Vor-Ort-Einsatz erforderlich.',
|
||||
isComment: false,
|
||||
$createdAt: threeDaysAgo.toISOString()
|
||||
},
|
||||
{
|
||||
$id: 'ws-10001-002',
|
||||
wsid: '100002',
|
||||
woid: '10001',
|
||||
workorderId: 'dummy-10001',
|
||||
employeeId: 'user-lisa-id',
|
||||
employeeName: 'Lisa Schneider',
|
||||
employeeShort: 'LS',
|
||||
serviceType: 'On Site',
|
||||
oldStatus: 'Occupied',
|
||||
newStatus: 'Assigned',
|
||||
oldResponseLevel: '24/7',
|
||||
newResponseLevel: '24/7',
|
||||
totalTime: 120,
|
||||
startDate: '23.12.2025',
|
||||
startTime: '1000',
|
||||
endDate: '23.12.2025',
|
||||
endTime: '1200',
|
||||
details: 'Vor-Ort-Einsatz: Hardware-Check durchgeführt. Netzteil des Hauptservers defekt. Ersatzteil bestellt. Notfall-Backup-Server gestartet.',
|
||||
isComment: false,
|
||||
$createdAt: threeDaysAgo.toISOString()
|
||||
},
|
||||
{
|
||||
$id: 'ws-10001-003',
|
||||
wsid: '100003',
|
||||
woid: '10001',
|
||||
workorderId: 'dummy-10001',
|
||||
employeeId: 'user-tom-id',
|
||||
employeeName: 'Tom Klein',
|
||||
employeeShort: 'TK',
|
||||
serviceType: 'On Site',
|
||||
oldStatus: 'Assigned',
|
||||
newStatus: 'Assigned',
|
||||
oldResponseLevel: '24/7',
|
||||
newResponseLevel: '24/7',
|
||||
totalTime: 0,
|
||||
startDate: '24.12.2025',
|
||||
startTime: '1400',
|
||||
endDate: '24.12.2025',
|
||||
endTime: '1400',
|
||||
details: 'Warte auf Ersatzteil-Lieferung. Kunde informiert. Backup-System läuft stabil.',
|
||||
isComment: true,
|
||||
$createdAt: twoDaysAgo.toISOString()
|
||||
},
|
||||
{
|
||||
$id: 'ws-10001-004',
|
||||
wsid: '100004',
|
||||
woid: '10001',
|
||||
workorderId: 'dummy-10001',
|
||||
employeeId: 'user-max-id',
|
||||
employeeName: 'Max Mustermann',
|
||||
employeeShort: 'MM',
|
||||
serviceType: 'On Site',
|
||||
oldStatus: 'Assigned',
|
||||
newStatus: 'In Test',
|
||||
oldResponseLevel: '24/7',
|
||||
newResponseLevel: '24/7',
|
||||
totalTime: 180,
|
||||
startDate: '25.12.2025',
|
||||
startTime: '0900',
|
||||
endDate: '25.12.2025',
|
||||
endTime: '1200',
|
||||
details: 'Ersatzteil eingebaut. Server gestartet. Alle Dienste wiederhergestellt. System-Tests durchgeführt. Datenbank-Verbindungen geprüft.',
|
||||
isComment: false,
|
||||
$createdAt: twoDaysAgo.toISOString()
|
||||
},
|
||||
{
|
||||
$id: 'ws-10001-005',
|
||||
wsid: '100005',
|
||||
woid: '10001',
|
||||
workorderId: 'dummy-10001',
|
||||
employeeId: 'user-lisa-id',
|
||||
employeeName: 'Lisa Schneider',
|
||||
employeeShort: 'LS',
|
||||
serviceType: 'Remote',
|
||||
oldStatus: 'In Test',
|
||||
newStatus: 'Awaiting',
|
||||
oldResponseLevel: '24/7',
|
||||
newResponseLevel: 'Support',
|
||||
totalTime: 45,
|
||||
startDate: '26.12.2025',
|
||||
startTime: '1000',
|
||||
endDate: '26.12.2025',
|
||||
endTime: '1045',
|
||||
details: 'Remote-Monitoring eingerichtet. Warte auf Kunden-Feedback nach 24h Testphase. Alle Systeme laufen stabil.',
|
||||
isComment: false,
|
||||
$createdAt: yesterday.toISOString()
|
||||
},
|
||||
{
|
||||
$id: 'ws-10001-006',
|
||||
wsid: '100006',
|
||||
woid: '10001',
|
||||
workorderId: 'dummy-10001',
|
||||
employeeId: 'user-tom-id',
|
||||
employeeName: 'Tom Klein',
|
||||
employeeShort: 'TK',
|
||||
serviceType: 'COMMENT',
|
||||
oldStatus: 'Awaiting',
|
||||
newStatus: 'Closed',
|
||||
oldResponseLevel: 'Support',
|
||||
newResponseLevel: 'Backoffice',
|
||||
totalTime: 0,
|
||||
startDate: '30.12.2025',
|
||||
startTime: '0900',
|
||||
endDate: '30.12.2025',
|
||||
endTime: '0900',
|
||||
details: 'Kunde bestätigt: Alle Systeme funktionieren einwandfrei. Problem vollständig behoben. Ticket kann geschlossen werden.',
|
||||
isComment: true,
|
||||
$createdAt: new Date().toISOString()
|
||||
}
|
||||
]
|
||||
|
||||
export function useWorksheets(woid = null) {
|
||||
const [worksheets, setWorksheets] = useState([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
@@ -158,16 +16,6 @@ export function useWorksheets(woid = null) {
|
||||
}
|
||||
setLoading(true)
|
||||
|
||||
if (DEMO_MODE) {
|
||||
// Filter demo data by WOID if provided
|
||||
const filtered = woid
|
||||
? DEMO_WORKSHEETS.filter(ws => ws.woid === woid)
|
||||
: DEMO_WORKSHEETS
|
||||
setWorksheets(filtered)
|
||||
setLoading(false)
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
// Ohne limit liefert Appwrite nur 25 Eintraege, ein Ticket sammelt aber viele Git-Pushes
|
||||
const queries = [Query.orderDesc('$createdAt'), Query.equal('woid', woid), Query.limit(5000)]
|
||||
@@ -212,13 +60,6 @@ export function useWorksheets(woid = null) {
|
||||
* Startet bei 100000 und zählt sequentiell hoch
|
||||
*/
|
||||
const generateWSID = useCallback(async () => {
|
||||
if (DEMO_MODE) {
|
||||
const maxWsid = worksheets.length > 0
|
||||
? Math.max(...worksheets.map(ws => parseInt(ws.wsid)).filter(w => !isNaN(w)))
|
||||
: 99999
|
||||
return (maxWsid + 1).toString()
|
||||
}
|
||||
|
||||
try {
|
||||
// Hole ALLE Worksheets (nicht gefiltert) um höchste WSID zu finden
|
||||
const response = await databases.listDocuments(
|
||||
@@ -287,18 +128,6 @@ export function useWorksheets(woid = null) {
|
||||
* Erstellt ein neues Worksheet
|
||||
*/
|
||||
const createWorksheet = async (data, currentUser) => {
|
||||
if (DEMO_MODE) {
|
||||
const wsid = await generateWSID()
|
||||
const newWs = {
|
||||
...data,
|
||||
$id: Date.now().toString(),
|
||||
wsid,
|
||||
$createdAt: new Date().toISOString()
|
||||
}
|
||||
setWorksheets(prev => [newWs, ...prev])
|
||||
return { success: true, data: newWs }
|
||||
}
|
||||
|
||||
try {
|
||||
// Validierung
|
||||
if (!data.woid || data.woid.trim() === '') {
|
||||
@@ -371,11 +200,6 @@ export function useWorksheets(woid = null) {
|
||||
* Aktualisiert ein Worksheet
|
||||
*/
|
||||
const updateWorksheet = async (id, data) => {
|
||||
if (DEMO_MODE) {
|
||||
setWorksheets(prev => prev.map(ws => ws.$id === id ? { ...ws, ...data } : ws))
|
||||
return { success: true }
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await databases.updateDocument(
|
||||
DATABASE_ID,
|
||||
@@ -410,11 +234,6 @@ export function useWorksheets(woid = null) {
|
||||
* Löscht ein Worksheet (sollte normalerweise nicht erlaubt sein - Audit Trail!)
|
||||
*/
|
||||
const deleteWorksheet = async (id) => {
|
||||
if (DEMO_MODE) {
|
||||
setWorksheets(prev => prev.filter(ws => ws.$id !== id))
|
||||
return { success: true }
|
||||
}
|
||||
|
||||
try {
|
||||
await databases.deleteDocument(
|
||||
DATABASE_ID,
|
||||
|
||||
@@ -8,14 +8,10 @@ export const projectId = (
|
||||
import.meta.env.VITE_APPWRITE_PROJECT_ID || DEFAULT_PROJECT_ID
|
||||
).trim()
|
||||
|
||||
/** Demo-Modus nur wenn wirklich keine Projekt-ID (sollte mit Defaults nie passieren) */
|
||||
export const isDemoMode = !projectId
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
console.log('🔧 Appwrite Konfiguration:')
|
||||
console.log('Endpoint:', endpoint)
|
||||
console.log('Project ID:', projectId || 'NICHT GESETZT')
|
||||
console.log('Demo-Modus:', isDemoMode)
|
||||
console.log('Database ID:', import.meta.env.VITE_APPWRITE_DATABASE_ID || 'woms-database')
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user