Stelle Website-Projekte und Admin-Tabs nach Auto-Deploy-Reset wieder her.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
8d62e353cb
commit
fda673702e
10 files changed
+543
-110
No files matched your search
@@ -7,7 +7,7 @@ const DEMO_MODE = isDemoMode
|
||||
const DEFAULT_CONFIG = {
|
||||
ticketTypes: [
|
||||
'Home Office', 'Holidays', 'Trip', 'Supportrequest', 'Change Request',
|
||||
'Maintenance', 'Project', 'Controlling', 'Development', 'Documentation',
|
||||
'Maintenance', 'Project', 'Webpage', 'Controlling', 'Development', 'Documentation',
|
||||
'Meeting/Conference', 'IT Management', 'IT Security', 'Procurement',
|
||||
'Rollout', 'Emergency Call', 'Other Services'
|
||||
],
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
import { useState, useCallback } from 'react'
|
||||
import { databases, DATABASE_ID, COLLECTIONS, Query, PREVIEW_TEMPLATE_NAME, isDemoMode } from '../lib/appwrite'
|
||||
|
||||
function isTemplateProject(project) {
|
||||
const template = project.templateName || PREVIEW_TEMPLATE_NAME
|
||||
return template === PREVIEW_TEMPLATE_NAME || Boolean(project.repoFullName)
|
||||
}
|
||||
|
||||
export function useWebsiteProjects() {
|
||||
const [projects, setProjects] = useState([])
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [error, setError] = useState(null)
|
||||
|
||||
const fetchAllProjects = useCallback(async () => {
|
||||
if (isDemoMode) return []
|
||||
setLoading(true)
|
||||
setError(null)
|
||||
try {
|
||||
const response = await databases.listDocuments(
|
||||
DATABASE_ID, COLLECTIONS.WEBSITE_PROJECTS,
|
||||
[Query.orderDesc('$createdAt'), Query.limit(500)]
|
||||
)
|
||||
setProjects(response.documents)
|
||||
return response.documents
|
||||
} catch (err) {
|
||||
setError(err.message)
|
||||
return []
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const fetchByTicketId = useCallback(async (ticketId) => {
|
||||
if (!ticketId || isDemoMode) return []
|
||||
try {
|
||||
const response = await databases.listDocuments(
|
||||
DATABASE_ID, COLLECTIONS.WEBSITE_PROJECTS,
|
||||
[Query.equal('ticketId', ticketId), Query.limit(100)]
|
||||
)
|
||||
return response.documents
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
}, [])
|
||||
|
||||
const getAvailableProjects = useCallback((allProjects, customerId) => {
|
||||
return (allProjects || []).filter(isTemplateProject).filter((p) => {
|
||||
if (!p.customerId) return true
|
||||
return customerId && p.customerId === customerId
|
||||
})
|
||||
}, [])
|
||||
|
||||
const assignProject = async (projectId, { customerId, ticketId }) => {
|
||||
try {
|
||||
const response = await databases.updateDocument(
|
||||
DATABASE_ID, COLLECTIONS.WEBSITE_PROJECTS, projectId,
|
||||
{ customerId, ticketId, updatedAt: new Date().toISOString() }
|
||||
)
|
||||
setProjects((prev) => prev.map((p) => (p.$id === projectId ? response : p)))
|
||||
return { success: true }
|
||||
} catch (err) {
|
||||
return { success: false, error: err.message }
|
||||
}
|
||||
}
|
||||
|
||||
const assignProjects = async (projectIds, ctx) => {
|
||||
const results = await Promise.all(projectIds.map((id) => assignProject(id, ctx)))
|
||||
return results.find((r) => !r.success) || { success: true }
|
||||
}
|
||||
|
||||
const unassignProject = async (projectId) => {
|
||||
try {
|
||||
await databases.updateDocument(
|
||||
DATABASE_ID, COLLECTIONS.WEBSITE_PROJECTS, projectId,
|
||||
{ customerId: '', ticketId: '', updatedAt: new Date().toISOString() }
|
||||
)
|
||||
return { success: true }
|
||||
} catch (err) {
|
||||
return { success: false, error: err.message }
|
||||
}
|
||||
}
|
||||
|
||||
return { projects, loading, error, fetchAllProjects, fetchByTicketId, getAvailableProjects, assignProjects, unassignProject }
|
||||
}
|
||||
+49
-34
@@ -1,8 +1,19 @@
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
import { useState, useEffect, useCallback, useMemo } from 'react'
|
||||
import { databases, DATABASE_ID, COLLECTIONS, Query, ID, isDemoMode } from '../lib/appwrite'
|
||||
|
||||
const DEMO_MODE = isDemoMode
|
||||
|
||||
function buildFiltersKey(filters = {}) {
|
||||
return JSON.stringify({
|
||||
limit: filters.limit ?? null,
|
||||
customerId: filters.customerId ?? null,
|
||||
assignedTo: filters.assignedTo ?? null,
|
||||
status: filters.status ?? null,
|
||||
type: filters.type ?? null,
|
||||
priority: filters.priority ?? null,
|
||||
})
|
||||
}
|
||||
|
||||
// Demo data for testing without Appwrite
|
||||
const lastWeek = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)
|
||||
|
||||
@@ -69,21 +80,30 @@ export function useWorkorders(filters = {}) {
|
||||
const [workorders, setWorkorders] = useState([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [error, setError] = useState(null)
|
||||
const filtersKey = useMemo(() => buildFiltersKey(filters), [
|
||||
filters.limit,
|
||||
filters.customerId,
|
||||
filters.assignedTo,
|
||||
filters.status,
|
||||
filters.type,
|
||||
filters.priority,
|
||||
])
|
||||
|
||||
const fetchWorkorders = useCallback(async () => {
|
||||
const activeFilters = JSON.parse(filtersKey)
|
||||
setLoading(true)
|
||||
|
||||
if (DEMO_MODE) {
|
||||
// Filter demo data
|
||||
let filtered = [...DEMO_WORKORDERS]
|
||||
if (filters.status?.length > 0) {
|
||||
filtered = filtered.filter(wo => filters.status.includes(wo.status))
|
||||
if (activeFilters.status?.length > 0) {
|
||||
filtered = filtered.filter(wo => activeFilters.status.includes(wo.status))
|
||||
}
|
||||
if (filters.priority?.length > 0) {
|
||||
filtered = filtered.filter(wo => filters.priority.includes(wo.priority))
|
||||
if (activeFilters.priority?.length > 0) {
|
||||
filtered = filtered.filter(wo => activeFilters.priority.includes(wo.priority))
|
||||
}
|
||||
if (filters.limit) {
|
||||
filtered = filtered.slice(0, filters.limit)
|
||||
if (activeFilters.limit) {
|
||||
filtered = filtered.slice(0, activeFilters.limit)
|
||||
}
|
||||
setWorkorders(filtered)
|
||||
setLoading(false)
|
||||
@@ -93,39 +113,34 @@ export function useWorkorders(filters = {}) {
|
||||
try {
|
||||
const queries = [Query.orderDesc('$createdAt')]
|
||||
|
||||
if (filters.limit) {
|
||||
queries.push(Query.limit(filters.limit))
|
||||
if (activeFilters.limit) {
|
||||
queries.push(Query.limit(activeFilters.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) {
|
||||
if (filters.status.length === 1) {
|
||||
queries.push(Query.equal('status', filters.status[0]))
|
||||
if (activeFilters.status && activeFilters.status.length > 0) {
|
||||
if (activeFilters.status.length === 1) {
|
||||
queries.push(Query.equal('status', activeFilters.status[0]))
|
||||
}
|
||||
// Für mehrere Werte: Clientseitig filtern (siehe unten)
|
||||
}
|
||||
|
||||
if (filters.type && filters.type.length > 0) {
|
||||
if (filters.type.length === 1) {
|
||||
queries.push(Query.equal('type', filters.type[0]))
|
||||
if (activeFilters.type && activeFilters.type.length > 0) {
|
||||
if (activeFilters.type.length === 1) {
|
||||
queries.push(Query.equal('type', activeFilters.type[0]))
|
||||
}
|
||||
// Für mehrere Werte: Clientseitig filtern
|
||||
}
|
||||
|
||||
if (filters.priority && filters.priority.length > 0) {
|
||||
if (filters.priority.length === 1) {
|
||||
queries.push(Query.equal('priority', filters.priority[0]))
|
||||
if (activeFilters.priority && activeFilters.priority.length > 0) {
|
||||
if (activeFilters.priority.length === 1) {
|
||||
queries.push(Query.equal('priority', activeFilters.priority[0]))
|
||||
}
|
||||
// Für mehrere Werte: Clientseitig filtern
|
||||
}
|
||||
|
||||
if (filters.customerId) {
|
||||
queries.push(Query.equal('customerId', filters.customerId))
|
||||
if (activeFilters.customerId) {
|
||||
queries.push(Query.equal('customerId', activeFilters.customerId))
|
||||
}
|
||||
|
||||
if (filters.assignedTo) {
|
||||
queries.push(Query.equal('assignedTo', filters.assignedTo))
|
||||
if (activeFilters.assignedTo) {
|
||||
queries.push(Query.equal('assignedTo', activeFilters.assignedTo))
|
||||
}
|
||||
|
||||
// Debug: Zeige Collection ID
|
||||
@@ -145,16 +160,16 @@ export function useWorkorders(filters = {}) {
|
||||
// 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 (activeFilters.status && activeFilters.status.length > 1) {
|
||||
filteredDocs = filteredDocs.filter(doc => activeFilters.status.includes(doc.status))
|
||||
}
|
||||
|
||||
if (filters.type && filters.type.length > 1) {
|
||||
filteredDocs = filteredDocs.filter(doc => filters.type.includes(doc.type))
|
||||
if (activeFilters.type && activeFilters.type.length > 1) {
|
||||
filteredDocs = filteredDocs.filter(doc => activeFilters.type.includes(doc.type))
|
||||
}
|
||||
|
||||
if (filters.priority && filters.priority.length > 1) {
|
||||
filteredDocs = filteredDocs.filter(doc => filters.priority.includes(doc.priority))
|
||||
if (activeFilters.priority && activeFilters.priority.length > 1) {
|
||||
filteredDocs = filteredDocs.filter(doc => activeFilters.priority.includes(doc.priority))
|
||||
}
|
||||
|
||||
setWorkorders(filteredDocs)
|
||||
@@ -174,7 +189,7 @@ export function useWorkorders(filters = {}) {
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}, [filters])
|
||||
}, [filtersKey])
|
||||
|
||||
useEffect(() => {
|
||||
fetchWorkorders()
|
||||
|
||||
Reference in new issue
Block a user