Tickets: Arbeitsblatt-Zeilen (.ws), Kennzahlen, Dringend-Schalter und Weitere Tickets im neuen Look

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-10-06 06:02:55 +00:00
1 parent ab42918bbc
commit 6eb5ab3679
6 files changed
+186 -381

No files matched your search

+17 -33
View File
@@ -1,17 +1,19 @@
import { useEffect, useState } from 'react'
import { Link } from 'react-router-dom'
import { IconFolders } from '@tabler/icons-react'
import { Link, useLocation } from 'react-router-dom'
import { Card } from './ui'
import { StatusPill } from './ui/StatusPill'
import { databases, DATABASE_ID, COLLECTIONS, Query } from '../lib/appwrite'
import { useWebsiteProjects } from '../hooks/useWebsiteProjects'
import { ticketPath, ticketRef } from '../lib/ticketRoutes'
import { ticketNumber } from '../lib/ticketView'
/**
* Projekt-Kontextbox im Ticket: zeigt automatisch das zugewiesene Projekt
* und alle anderen Tickets desselben Kunden (klickbar).
* Kontextbox im Ticket: "Weitere Tickets von <Kunde>" (klickbar).
* Rendert nichts, wenn dem Ticket kein Projekt zugewiesen ist.
*/
export default function ProjectContextPanel({ ticket }) {
const { fetchByTicketId } = useWebsiteProjects()
const location = useLocation()
const [context, setContext] = useState(null)
useEffect(() => {
@@ -23,7 +25,6 @@ export default function ProjectContextPanel({ ticket }) {
if (!cancelled) setContext(null)
return
}
const projectName = assignedProjects[0].projectName || ''
let otherTickets = []
if (ticket.customerId) {
@@ -34,7 +35,7 @@ export default function ProjectContextPanel({ ticket }) {
])
otherTickets = res.documents.filter((t) => t.$id !== ticket.$id)
}
if (!cancelled) setContext({ projectName, otherTickets })
if (!cancelled) setContext({ otherTickets })
} catch {
if (!cancelled) setContext(null)
}
@@ -44,44 +45,27 @@ export default function ProjectContextPanel({ ticket }) {
}, [ticket.$id, ticket.customerId, fetchByTicketId])
if (!context) return null
const { projectName, otherTickets } = context
const { otherTickets } = context
return (
<div className="ui-card pad" style={{ marginTop: 16 }}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12, flexWrap: 'wrap', marginBottom: 10 }}>
<h5 style={{ fontWeight: 700, margin: 0, display: 'flex', alignItems: 'center', gap: 8 }}>
<IconFolders size={18} /> Projekt: {projectName || '-'}
</h5>
</div>
<Card title={ticket.customerName ? `Weitere Tickets von ${ticket.customerName}` : 'Weitere Tickets'}>
{!ticket.customerId ? (
<p className="faint" style={{ fontSize: 13, margin: 0 }}>
Kein Kunde zugeordnet — andere Tickets koennen nicht automatisch verknuepft werden.
</p>
<p className="muted">Kein Kunde zugeordnet — andere Tickets koennen nicht automatisch verknuepft werden.</p>
) : !otherTickets.length ? (
<p className="faint" style={{ fontSize: 13, margin: 0 }}>
Keine weiteren Tickets zu diesem Kunden/Projekt.
</p>
<p className="muted">Keine weiteren Tickets zu diesem Kunden/Projekt.</p>
) : (
<div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
<div>
{otherTickets.map((t) => (
<Link
key={t.$id}
to={`/tickets?woid=${t.woid}`}
style={{
display: 'flex', alignItems: 'center', gap: 10, fontSize: 13, color: 'var(--text)', textDecoration: 'none',
padding: '6px 8px', borderRadius: 8, border: '1px solid var(--border)',
}}
>
<span className="muted" style={{ minWidth: 48, fontWeight: 700 }}>{t.woid}</span>
<span style={{ flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
{t.topic || t.title || '-'}
<Link key={t.$id} className="list-row" to={ticketPath(ticketRef(t))} state={location.state}>
<span className="cell-title list-row-text">
<span className="id">{ticketNumber(t)}</span>
<span>{t.topic || t.title || '-'}</span>
</span>
<StatusPill status={t.status} />
</Link>
))}
</div>
)}
</div>
</Card>
)
}