Projektarten: Ablauf-Logik und API-Client

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-09-30 17:39:19 +00:00
1 parent 24e4f054c4
commit 9dc447e92c
3 files changed
+170

No files matched your search

+57
View File
@@ -0,0 +1,57 @@
// Ablauf-Logik des Zuordnen-Assistenten (reine Funktionen, ohne UI).
// state: { step, kind, forCustomer, customerId, ticketId, newTicket }
export function nextStep(state) {
switch (state.step) {
case 'kind':
return 'customer?'
case 'customer?':
return state.forCustomer ? 'customer' : 'summary'
case 'customer':
return 'ticket'
default:
return 'summary'
}
}
export function prevStep(state) {
switch (state.step) {
case 'customer?':
return 'kind'
case 'customer':
return 'customer?'
case 'ticket':
return 'customer'
case 'summary':
return state.forCustomer ? 'ticket' : 'customer?'
default:
return 'kind'
}
}
export function newTicketDefaults({ kindLabel, ticketType, repoName, repoUrl, customer, today }) {
return {
topic: `${kindLabel} – ${repoName}`,
type: ticketType,
requestedBy: customer?.contactName || customer?.name || '',
startDate: today,
details: `Repository: ${repoUrl}`,
}
}
const filled = (v) => typeof v === 'string' && v.trim() !== ''
export function canFinish(state) {
if (!state.kind) return false
if (!state.forCustomer) return true
if (!state.customerId) return false
if (state.ticketId) return true
const t = state.newTicket
return !!t && filled(t.topic) && filled(t.requestedBy) && filled(t.startDate)
}
export function openTicketsFor(tickets, customerId) {
return (tickets || []).filter(
(t) => t.customerId === customerId && t.status !== 'Closed' && t.status !== 'Cancelled'
)
}
+41
View File
@@ -0,0 +1,41 @@
import { account, databases, DATABASE_ID, COLLECTIONS } from './appwrite'
const PROJECT_ADMIN_URL =
import.meta.env.VITE_PROJECT_ADMIN_URL || 'https://project.webklar.com'
// Wie adminFetch in projectAdminApi.js, aber der Fehler trägt .status und .data
// (Antwort-Body), damit die Seite z. B. die Details eines 409 anzeigen kann.
async function kindsFetch(path, options = {}) {
const jwt = await account.createJWT()
const response = await fetch(`${PROJECT_ADMIN_URL}${path}`, {
...options,
headers: {
Authorization: `Bearer ${jwt.jwt}`,
'Content-Type': 'application/json',
...options.headers,
},
})
const data = await response.json().catch(() => ({}))
if (!response.ok) {
const error = new Error(data.error || `API-Fehler ${response.status}`)
error.status = response.status
error.data = data
throw error
}
return data
}
export function fetchServices() {
return kindsFetch('/api/admin/services')
}
export function completeAssignment(projectId, body) {
return kindsFetch(`/api/admin/website-projects/${projectId}/zuordnen`, {
method: 'POST',
body: JSON.stringify(body),
})
}
export function fetchProject(projectId) {
return databases.getDocument(DATABASE_ID, COLLECTIONS.WEBSITE_PROJECTS, projectId)
}