Tickets auf WEBklar zugeschnitten (Paket B)

- Status: 6 statt 10, auf Deutsch (Offen, In Arbeit, Wartet auf Kunde,
  Prüfung, Erledigt, Storniert). Gespeichert werden die Werte, die das
  Kundenportal für die Fortschrittsleiste kennt; alte Werte wie Assigned
  werden weiter angezeigt ("Eingeplant"), sind aber nicht mehr wählbar.
- Zuweisen ändert den Status nicht mehr; neue Tickets starten "Offen".
- Priorität: Schalter "Dringend" statt fünf Stufen (dringend = 4, normal
  = 2; alte Stufen Hoch/Kritisch gelten als dringend), rotes Abzeichen.
- Ticketliste: Standardansicht "Aufträge" ohne Akquise-Tickets; Filter
  Typ (Aufträge/Webpage/Migration/Projekt/Akquise/Alle), 6 Status-Gruppen,
  "Nur dringende". Die toten Felder Kunde, Benutzer/Thema und Datum sind
  durch eine echte Suche ersetzt (Kunde, Betreff, Angefragt von, WOID).
  Deep-Link ?woid= zeigt das Ticket weiter unabhängig von Art und Status.
- Formulare "Neues Ticket" und "Arbeitsblatt" auf Deutsch; raus sind
  Workload Estimate, Requested for und die Service-Art am Ticket
  (gespeichert wird weiter Fernwartung).
- Ticketkarte: Projekt/Preview im Details-Reiter (4 statt 5 Reiter), eine
  Zusammenfassungszeile statt der großen Statistik, doppelter
  Projekte-Stift weg, Service-Abzeichen weg.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-09-27 15:46:03 +00:00
1 parent bf007df737
commit 062d992b63
17 files changed
+359 -626

No files matched your search

+18 -29
View File
@@ -3,12 +3,12 @@ import { FaChevronDown, FaPlay, FaStop, FaPlus, FaPen } from 'react-icons/fa6'
import { formatDistanceToNow, format } from 'date-fns'
import { de } from 'date-fns/locale'
import StatusDropdown from './StatusDropdown'
import PriorityDropdown from './PriorityDropdown'
import UrgentToggle from './UrgentToggle'
import EditorDropdown from './EditorDropdown'
import CreateWorksheetModal from './CreateWorksheetModal'
import WorksheetList from './WorksheetList'
import WorksheetTimesModal from './WorksheetTimesModal'
import WorksheetStats from './WorksheetStats'
import WorksheetSummary from './WorksheetSummary'
import TicketAssignedProjectsPanel from './TicketAssignedProjectsPanel'
import TicketProjectsModal from './TicketProjectsModal'
import TicketRoadmapPanel from './TicketRoadmapPanel'
@@ -17,18 +17,19 @@ import InvoicePanel from './InvoicePanel'
import DocumentsPanel from './DocumentsPanel'
import Tabs from './ui/Tabs'
import Badge from './ui/Badge'
import { StatusPill, PriorityPill } from './ui/StatusPill'
import { StatusPill, UrgentPill } from './ui/StatusPill'
import { useWorksheets } from '../hooks/useWorksheets'
import { useAuth } from '../context/AuthContext'
import { databases, DATABASE_ID, COLLECTIONS } from '../lib/appwrite'
import { serviceTypeLabel, canEditWorksheetTimes } from '../lib/ticketForm'
import { canEditWorksheetTimes } from '../lib/ticketForm'
import { ticketTypeLabel } from '../lib/ticketStatus'
// Projekt / Preview steht mit im Details-Reiter
const TABS = [
{ id: 'details', label: 'Details' },
{ id: 'worksheets', label: 'Arbeitsblaetter' },
{ id: 'worksheets', label: 'Arbeitsblätter' },
{ id: 'invoices', label: 'Rechnungen' },
{ id: 'documents', label: 'Dokumente' },
{ id: 'project', label: 'Projekt / Preview' },
]
export default function TicketCard({ ticket, onUpdate }) {
@@ -89,9 +90,8 @@ export default function TicketCard({ ticket, onUpdate }) {
<div className="tcard-topic">{ticket.topic || ticket.title || 'Kein Betreff'}</div>
<div className="tcard-badges">
<StatusPill status={ticket.status} />
<PriorityPill priority={ticket.priority} />
{ticket.type && <Badge tone="muted">{ticket.type}</Badge>}
{ticket.serviceType && <Badge tone="info">{serviceTypeLabel(ticket.serviceType)}</Badge>}
<UrgentPill priority={ticket.priority} />
{ticket.type && <Badge tone="muted">{ticketTypeLabel(ticket.type)}</Badge>}
</div>
</div>
@@ -99,9 +99,7 @@ export default function TicketCard({ ticket, onUpdate }) {
<div style={{ minWidth: 120 }}>
<StatusDropdown value={ticket.status} onChange={(v) => onUpdate(ticket.$id, { status: v })} />
</div>
<div style={{ minWidth: 110 }}>
<PriorityDropdown value={ticket.priority} onChange={(v) => onUpdate(ticket.$id, { priority: v })} />
</div>
<UrgentToggle value={ticket.priority} onChange={(v) => onUpdate(ticket.$id, { priority: v })} />
<FaChevronDown className={`chevron ${expanded ? 'up' : ''}`} onClick={() => setExpanded((e) => !e)} style={{ cursor: 'pointer' }} />
</div>
</div>
@@ -121,13 +119,18 @@ export default function TicketCard({ ticket, onUpdate }) {
<div className="ticket-tab-content">
{activeTab === 'details' && (
<div>
<div className="ui-card pad">
<div className="ui-card pad" style={{ marginBottom: 16 }}>
<h5 style={{ fontWeight: 700, marginBottom: 12 }}>Ticket-Beschreibung</h5>
<p style={{ whiteSpace: 'pre-wrap', color: 'var(--text-muted)', lineHeight: 1.7, margin: 0 }}>
{ticket.details || 'Keine Details vorhanden.'}
</p>
</div>
<ProjectContextPanel ticket={ticket} />
<TicketRoadmapPanel ticket={ticket} />
<button className="ui-btn ui-btn-primary" style={{ marginBottom: 12 }} onClick={() => setShowProjectsModal(true)}>
<FaPen /> Projekte zuweisen / bearbeiten
</button>
<TicketAssignedProjectsPanel ticket={ticket} refreshKey={projectsRefreshKey} />
</div>
)}
@@ -135,15 +138,10 @@ export default function TicketCard({ ticket, onUpdate }) {
<div>
<div className="flex gap-2" style={{ marginBottom: 16 }}>
<button className="ui-btn ui-btn-primary grow" onClick={() => setShowCreateWorksheet(true)}>
<FaPlus /> Arbeitsblatt hinzufuegen
<FaPlus /> Arbeitsblatt hinzufügen
</button>
<button className="ui-btn" onClick={() => setShowProjectsModal(true)} title="Projekte"><FaPen /></button>
</div>
{worksheets.length > 0 && (
<div className="ui-card pad" style={{ marginBottom: 16 }}>
<WorksheetStats worksheets={worksheets} />
</div>
)}
<WorksheetSummary worksheets={worksheets} />
<WorksheetList
worksheets={worksheets}
totalTime={getTotalTime()}
@@ -157,15 +155,6 @@ export default function TicketCard({ ticket, onUpdate }) {
{activeTab === 'invoices' && <InvoicePanel ticket={ticket} />}
{activeTab === 'documents' && <DocumentsPanel ticket={ticket} />}
{activeTab === 'project' && (
<div>
<TicketRoadmapPanel ticket={ticket} />
<button className="ui-btn ui-btn-primary" style={{ marginBottom: 12 }} onClick={() => setShowProjectsModal(true)}>
<FaPen /> Projekte zuweisen / bearbeiten
</button>
<TicketAssignedProjectsPanel ticket={ticket} refreshKey={projectsRefreshKey} />
</div>
)}
</div>
</div>
)}