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:
ClaudeandClaude Opus 5.5 committed 2026-09-27 14:36:33 +00:00
1 parent 889a2f42eb
commit b758b1f9a7
11 files changed
+25 -451

No files matched your search

+2 -2
View File
@@ -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)])
+1 -26
View File
@@ -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) {
+2 -16
View File
@@ -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,
-44
View File
@@ -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
View File
@@ -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) {
+2 -7
View File
@@ -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 })
+2 -8
View File
@@ -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)))
+2 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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,
-4
View File
@@ -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')
}