Schnellübersicht und Status-Verlauf entfernt
- "Schnelluebersicht" war eine englische Alt-Tabelle ("WOMS Ticket Quick
Overview ... EOL =)"), die nur die Ticketliste wiederholte.
- Der "Verlauf"-Knopf zeigte nur Statuswechsel aus Arbeitsblättern (bisher
zwei); jeder Wechsel steht weiterhin im jeweiligen Arbeitsblatt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
cbf77004ad
commit
8d2a99e5d6
5 files changed
+2
-259
No files matched your search
@@ -1,87 +0,0 @@
|
||||
import { FaTimes } from 'react-icons/fa'
|
||||
import { format } from 'date-fns'
|
||||
|
||||
const STATUS_CLASSES = {
|
||||
'Open': 'bg-red',
|
||||
'Occupied': 'bg-blue-grey',
|
||||
'Assigned': 'bg-teal',
|
||||
'Awaiting': 'bg-amber',
|
||||
'Closed': 'bg-grey'
|
||||
}
|
||||
|
||||
const PRIORITY_CLASSES = {
|
||||
0: 'bg-blue',
|
||||
1: 'bg-green',
|
||||
2: 'bg-amber',
|
||||
3: 'bg-orange',
|
||||
4: 'bg-red'
|
||||
}
|
||||
|
||||
const PRIORITY_LABELS = {
|
||||
0: 'NONE',
|
||||
1: 'LOW',
|
||||
2: 'MEDIUM',
|
||||
3: 'HIGH',
|
||||
4: 'CRITICAL'
|
||||
}
|
||||
|
||||
export default function QuickOverviewModal({ isOpen, onClose, workorders = [] }) {
|
||||
if (!isOpen) return null
|
||||
|
||||
return (
|
||||
<div className="overlay">
|
||||
<span className="overlay-close" onClick={onClose}>
|
||||
<FaTimes />
|
||||
</span>
|
||||
<div className="overlay-content">
|
||||
<h3 className="mb-2">WOMS Ticket Quick Overview</h3>
|
||||
|
||||
<table className="table" style={{ background: '#fff', color: '#000' }}>
|
||||
<thead>
|
||||
<tr className="bg-dark-grey text-white">
|
||||
<th>WOID</th>
|
||||
<th>Created</th>
|
||||
<th>Type</th>
|
||||
<th>CID & CLO</th>
|
||||
<th>Requested by</th>
|
||||
<th>Topic</th>
|
||||
<th className="text-center">Priority</th>
|
||||
<th className="text-right">Status</th>
|
||||
<th>Editor</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{workorders.map(wo => (
|
||||
<tr key={wo.$id} className="bg-white">
|
||||
<td className="bg-dark-grey text-white text-small">
|
||||
{wo.woid || wo.$id?.slice(-5)}
|
||||
</td>
|
||||
<td className="bg-light-grey text-small">
|
||||
{format(new Date(wo.$createdAt || wo.createdAt), 'dd.MM.yyyy, HH:mm')}h
|
||||
</td>
|
||||
<td className="bg-light-grey text-small">{wo.type}</td>
|
||||
<td className="text-small">{wo.customerCode} {wo.customerLocation}</td>
|
||||
<td className="text-small">{wo.requestedBy}</td>
|
||||
<td className="text-small">{wo.topic}</td>
|
||||
<td className={`text-small text-center ${PRIORITY_CLASSES[wo.priority]}`}>
|
||||
{PRIORITY_LABELS[wo.priority]}
|
||||
</td>
|
||||
<td className={`text-small text-right ${STATUS_CLASSES[wo.status]}`}>
|
||||
{wo.status?.toUpperCase()}
|
||||
</td>
|
||||
<td className={`text-small ${STATUS_CLASSES[wo.status]}`}>
|
||||
{wo.assignedTo || '-'}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p className="mt-2 text-center">
|
||||
Summary: Listed a total of {workorders.length} Workorders!
|
||||
<br />EOL =)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
import { FaTimes } from 'react-icons/fa'
|
||||
import { format } from 'date-fns'
|
||||
|
||||
export default function StatusHistoryModal({ isOpen, onClose, worksheets, ticket }) {
|
||||
if (!isOpen) return null
|
||||
|
||||
// Extrahiere Status-Änderungen aus Worksheets
|
||||
const statusHistory = worksheets
|
||||
.filter(ws => ws.oldStatus && ws.newStatus && ws.oldStatus !== ws.newStatus)
|
||||
.map(ws => ({
|
||||
date: ws.startDate,
|
||||
time: ws.startTime,
|
||||
from: ws.oldStatus,
|
||||
to: ws.newStatus,
|
||||
employee: ws.employeeName || ws.employeeShort || 'Unknown',
|
||||
details: ws.details,
|
||||
wsid: ws.wsid
|
||||
}))
|
||||
.sort((a, b) => {
|
||||
// Sortiere nach Datum und Zeit (älteste zuerst)
|
||||
const dateA = `${a.date} ${a.time || '0000'}`
|
||||
const dateB = `${b.date} ${b.time || '0000'}`
|
||||
return dateA.localeCompare(dateB)
|
||||
})
|
||||
|
||||
// Füge aktuellen Status hinzu
|
||||
const currentStatus = ticket?.status || 'Open'
|
||||
|
||||
return (
|
||||
<div className="overlay">
|
||||
<span className="overlay-close" onClick={onClose}>
|
||||
<FaTimes />
|
||||
</span>
|
||||
<div className="overlay-content">
|
||||
<h2 className="mb-2">Status History - WOID {ticket?.woid || ticket?.$id}</h2>
|
||||
|
||||
<div style={{ marginBottom: '24px' }}>
|
||||
<div style={{
|
||||
background: 'rgba(45, 55, 72, 0.95)',
|
||||
borderRadius: '8px',
|
||||
padding: '16px',
|
||||
border: '1px solid rgba(16, 185, 129, 0.2)',
|
||||
marginBottom: '16px'
|
||||
}}>
|
||||
<strong style={{ color: 'var(--green-primary)' }}>Current Status:</strong>
|
||||
<span style={{
|
||||
marginLeft: '12px',
|
||||
padding: '4px 12px',
|
||||
borderRadius: '4px',
|
||||
background: 'rgba(16, 185, 129, 0.2)',
|
||||
color: 'var(--dark-text)',
|
||||
fontWeight: 'bold'
|
||||
}}>
|
||||
{currentStatus}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{statusHistory.length === 0 ? (
|
||||
<div style={{
|
||||
background: 'rgba(45, 55, 72, 0.95)',
|
||||
borderRadius: '8px',
|
||||
padding: '24px',
|
||||
textAlign: 'center',
|
||||
color: '#a0aec0'
|
||||
}}>
|
||||
No status changes recorded yet.
|
||||
</div>
|
||||
) : (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
|
||||
{statusHistory.map((entry, index) => (
|
||||
<div
|
||||
key={index}
|
||||
style={{
|
||||
background: 'rgba(45, 55, 72, 0.95)',
|
||||
borderRadius: '8px',
|
||||
padding: '16px',
|
||||
border: '1px solid rgba(16, 185, 129, 0.2)',
|
||||
borderLeft: '4px solid var(--green-primary)'
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'start', marginBottom: '8px' }}>
|
||||
<div>
|
||||
<div style={{ fontSize: '14px', color: '#a0aec0', marginBottom: '4px' }}>
|
||||
{entry.date} {entry.time ? `${entry.time.substring(0, 2)}:${entry.time.substring(2, 4)}` : ''}
|
||||
</div>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
|
||||
<span style={{
|
||||
padding: '4px 8px',
|
||||
borderRadius: '4px',
|
||||
background: 'rgba(74, 85, 104, 0.5)',
|
||||
color: 'var(--dark-text)',
|
||||
fontSize: '12px'
|
||||
}}>
|
||||
{entry.from}
|
||||
</span>
|
||||
<span style={{ color: 'var(--green-primary)' }}>→</span>
|
||||
<span style={{
|
||||
padding: '4px 8px',
|
||||
borderRadius: '4px',
|
||||
background: 'rgba(16, 185, 129, 0.3)',
|
||||
color: 'var(--dark-text)',
|
||||
fontSize: '12px',
|
||||
fontWeight: 'bold'
|
||||
}}>
|
||||
{entry.to}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ textAlign: 'right' }}>
|
||||
<div style={{ fontSize: '12px', color: '#a0aec0' }}>by</div>
|
||||
<div style={{ fontWeight: 'bold', color: 'var(--dark-text)' }}>{entry.employee}</div>
|
||||
{entry.wsid && (
|
||||
<div style={{ fontSize: '11px', color: '#718096', marginTop: '4px' }}>
|
||||
WSID: {entry.wsid}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{entry.details && (
|
||||
<div style={{
|
||||
marginTop: '12px',
|
||||
padding: '12px',
|
||||
background: 'rgba(31, 41, 55, 0.6)',
|
||||
borderRadius: '6px',
|
||||
fontSize: '13px',
|
||||
color: '#cbd5e0',
|
||||
borderLeft: '3px solid rgba(16, 185, 129, 0.4)'
|
||||
}}>
|
||||
{entry.details}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { useState } from 'react'
|
||||
import { FaChevronDown, FaPlay, FaStop, FaPlus, FaClockRotateLeft, FaPen } from 'react-icons/fa6'
|
||||
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 EditorDropdown from './EditorDropdown'
|
||||
import CreateWorksheetModal from './CreateWorksheetModal'
|
||||
import StatusHistoryModal from './StatusHistoryModal'
|
||||
import WorksheetList from './WorksheetList'
|
||||
import WorksheetTimesModal from './WorksheetTimesModal'
|
||||
import WorksheetStats from './WorksheetStats'
|
||||
@@ -38,7 +37,6 @@ export default function TicketCard({ ticket, onUpdate }) {
|
||||
const [activeTab, setActiveTab] = useState('details')
|
||||
const [showCreateWorksheet, setShowCreateWorksheet] = useState(false)
|
||||
const [editTimesWorksheet, setEditTimesWorksheet] = useState(null)
|
||||
const [showHistoryModal, setShowHistoryModal] = useState(false)
|
||||
const [showProjectsModal, setShowProjectsModal] = useState(false)
|
||||
const [projectsRefreshKey, setProjectsRefreshKey] = useState(0)
|
||||
|
||||
@@ -137,7 +135,6 @@ export default function TicketCard({ ticket, onUpdate }) {
|
||||
<FaPlus /> Arbeitsblatt hinzufuegen
|
||||
</button>
|
||||
<button className="ui-btn" onClick={() => setShowProjectsModal(true)} title="Projekte"><FaPen /></button>
|
||||
<button className="ui-btn" onClick={() => setShowHistoryModal(true)} title="Verlauf"><FaClockRotateLeft /></button>
|
||||
</div>
|
||||
{worksheets.length > 0 && (
|
||||
<div className="ui-card pad" style={{ marginBottom: 16 }}>
|
||||
@@ -177,7 +174,6 @@ export default function TicketCard({ ticket, onUpdate }) {
|
||||
onSave={(ws, times) => updateWorksheetTimes(ws, times, user, employee)}
|
||||
/>
|
||||
)}
|
||||
<StatusHistoryModal isOpen={showHistoryModal} onClose={() => setShowHistoryModal(false)} worksheets={worksheets} ticket={ticket} />
|
||||
<TicketProjectsModal isOpen={showProjectsModal} onClose={() => setShowProjectsModal(false)} ticket={ticket} onUpdated={() => setProjectsRefreshKey((k) => k + 1)} />
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -462,24 +462,6 @@ export function useWorksheets(woid = null) {
|
||||
}, {})
|
||||
}, [worksheets])
|
||||
|
||||
/**
|
||||
* Gibt die Status-Historie zurück (chronologisch)
|
||||
*/
|
||||
const getStatusHistory = useCallback(() => {
|
||||
return worksheets
|
||||
.filter(ws => ws.oldStatus && ws.newStatus)
|
||||
.map(ws => ({
|
||||
wsid: ws.wsid,
|
||||
date: ws.startDate,
|
||||
time: ws.startTime,
|
||||
employee: ws.employeeName,
|
||||
from: ws.oldStatus,
|
||||
to: ws.newStatus,
|
||||
details: ws.details
|
||||
}))
|
||||
.reverse() // Älteste zuerst
|
||||
}, [worksheets])
|
||||
|
||||
return {
|
||||
worksheets,
|
||||
loading,
|
||||
@@ -491,7 +473,6 @@ export function useWorksheets(woid = null) {
|
||||
refresh: fetchWorksheets,
|
||||
getTotalTime,
|
||||
getWorksheetsByEmployee,
|
||||
getStatusHistory,
|
||||
calculateTime
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useSearchParams } from 'react-router-dom'
|
||||
import { FaAngleDown, FaSpinner, FaPlus, FaList, FaSliders } from 'react-icons/fa6'
|
||||
import { FaAngleDown, FaSpinner, FaPlus, FaSliders } from 'react-icons/fa6'
|
||||
import { useWorkorders } from '../hooks/useWorkorders'
|
||||
import { useCustomers } from '../hooks/useCustomers'
|
||||
import TicketCard from '../components/TicketCard'
|
||||
import CreateTicketModal from '../components/CreateTicketModal'
|
||||
import QuickOverviewModal from '../components/QuickOverviewModal'
|
||||
import { PageHeader, Card, Button, EmptyState } from '../components/ui'
|
||||
|
||||
// Alle Ticket-Status; "Closed" gilt als archiviert und ist standardmaessig ausgeblendet
|
||||
@@ -34,7 +33,6 @@ export default function TicketsPage() {
|
||||
const { customers } = useCustomers()
|
||||
|
||||
const [showCreateModal, setShowCreateModal] = useState(false)
|
||||
const [showOverviewModal, setShowOverviewModal] = useState(false)
|
||||
const [showAdvanced, setShowAdvanced] = useState(false)
|
||||
const [searchParams] = useSearchParams()
|
||||
|
||||
@@ -82,7 +80,6 @@ export default function TicketsPage() {
|
||||
subtitle="Alle Arbeitsauftraege auf einen Blick"
|
||||
actions={
|
||||
<>
|
||||
<Button variant="ghost" onClick={() => setShowOverviewModal(true)}><FaList /> Schnelluebersicht</Button>
|
||||
<Button variant="ghost" onClick={() => setShowAdvanced((s) => !s)}><FaSliders /> Filter</Button>
|
||||
<Button variant="primary" onClick={() => setShowCreateModal(true)}><FaPlus /> Neues Ticket</Button>
|
||||
</>
|
||||
@@ -160,7 +157,6 @@ export default function TicketsPage() {
|
||||
)}
|
||||
|
||||
<CreateTicketModal isOpen={showCreateModal} onClose={() => setShowCreateModal(false)} onCreate={handleCreate} customers={customers} />
|
||||
<QuickOverviewModal isOpen={showOverviewModal} onClose={() => setShowOverviewModal(false)} workorders={workorders} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user