Projektarten: Zuordnen-Seite nachgebessert
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7e79dac6b4
commit
8653756935
1 file changed
+19
-7
@@ -44,6 +44,8 @@ export default function AssignProjectPage() {
|
||||
const [showNewCustomer, setShowNewCustomer] = useState(false)
|
||||
const [tickets, setTickets] = useState([])
|
||||
const [ticketsLoading, setTicketsLoading] = useState(false)
|
||||
const [ticketsError, setTicketsError] = useState(false)
|
||||
const [ticketsReload, setTicketsReload] = useState(0)
|
||||
const [previewOn, setPreviewOn] = useState(true)
|
||||
const [subdomain, setSubdomain] = useState('')
|
||||
const [busy, setBusy] = useState(false)
|
||||
@@ -75,17 +77,20 @@ export default function AssignProjectPage() {
|
||||
if (state.step !== 'ticket' || !state.customerId) return
|
||||
let cancelled = false
|
||||
setTicketsLoading(true)
|
||||
setTicketsError(false)
|
||||
databases
|
||||
.listDocuments(DATABASE_ID, COLLECTIONS.WORKORDERS, [
|
||||
Query.equal('customerId', state.customerId),
|
||||
Query.notEqual('status', 'Closed'),
|
||||
Query.notEqual('status', 'Cancelled'),
|
||||
Query.orderDesc('$createdAt'),
|
||||
Query.limit(200),
|
||||
])
|
||||
.then((r) => { if (!cancelled) setTickets(r.documents || []) })
|
||||
.catch(() => { if (!cancelled) setTickets([]) })
|
||||
.catch(() => { if (!cancelled) { setTickets([]); setTicketsError(true) } })
|
||||
.finally(() => { if (!cancelled) setTicketsLoading(false) })
|
||||
return () => { cancelled = true }
|
||||
}, [state.step, state.customerId])
|
||||
}, [state.step, state.customerId, ticketsReload])
|
||||
|
||||
const openTickets = useMemo(() => openTicketsFor(tickets, state.customerId), [tickets, state.customerId])
|
||||
|
||||
@@ -142,7 +147,7 @@ export default function AssignProjectPage() {
|
||||
}
|
||||
try {
|
||||
const result = await completeAssignment(id, body)
|
||||
let path = '/projects'
|
||||
let path = state.forCustomer ? '/projects' : '/services'
|
||||
if (result.ticketId) {
|
||||
try {
|
||||
const t = await databases.getDocument(DATABASE_ID, COLLECTIONS.WORKORDERS, result.ticketId)
|
||||
@@ -183,7 +188,7 @@ export default function AssignProjectPage() {
|
||||
<div style={{ fontWeight: 700, fontSize: 18 }}>{repoName || project.projectName}</div>
|
||||
<div className="muted" style={{ marginTop: 4 }}>
|
||||
{repoUrl && <a href={repoUrl} target="_blank" rel="noreferrer">Repository in Gitea öffnen</a>}
|
||||
{project.$createdAt && <> · angelegt am {fmtDate(project.$createdAt)}{project.createdByGitea ? ' (über Gitea)' : ''}</>}
|
||||
{project.$createdAt && <> · angelegt am {fmtDate(project.$createdAt)}{project.createdByGitea ? ` von ${project.createdByGitea}` : ''}</>}
|
||||
</div>
|
||||
</Card>
|
||||
)
|
||||
@@ -239,7 +244,7 @@ export default function AssignProjectPage() {
|
||||
key={k.key}
|
||||
variant={state.kind === k.key ? 'primary' : 'default'}
|
||||
style={{ padding: '18px 12px', fontSize: 16, fontWeight: 700 }}
|
||||
onClick={() => patch({ kind: k.key })}
|
||||
onClick={() => patch({ kind: k.key, newTicket: null, ticketId: '' })}
|
||||
>
|
||||
{k.label}
|
||||
</Button>
|
||||
@@ -298,7 +303,12 @@ export default function AssignProjectPage() {
|
||||
|
||||
{state.step === 'ticket' && (
|
||||
<>
|
||||
{ticketsLoading ? <FaSpinner className="spinner" /> : (
|
||||
{ticketsLoading ? <FaSpinner className="spinner" /> : ticketsError ? (
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<div className="text-red" style={{ marginBottom: 8 }}>Die Tickets des Kunden konnten nicht geladen werden.</div>
|
||||
<Button onClick={() => setTicketsReload((n) => n + 1)}>Erneut versuchen</Button>
|
||||
</div>
|
||||
) : (
|
||||
<div className="list" style={{ marginBottom: 12 }}>
|
||||
{openTickets.map((t) => (
|
||||
<div key={t.$id} className="list-row" style={{ cursor: 'pointer', background: state.ticketId === t.$id ? 'var(--surface-2)' : undefined }}
|
||||
@@ -313,7 +323,9 @@ export default function AssignProjectPage() {
|
||||
{openTickets.length === 0 && <div className="muted" style={{ padding: 12 }}>Dieser Kunde hat keine offenen Tickets.</div>}
|
||||
</div>
|
||||
)}
|
||||
<Button variant={state.newTicket ? 'primary' : 'default'} onClick={startNewTicket}><FaPlus /> Neues Ticket anlegen</Button>
|
||||
{!ticketsError && !ticketsLoading && (
|
||||
<Button variant={state.newTicket ? 'primary' : 'default'} onClick={startNewTicket}><FaPlus /> Neues Ticket anlegen</Button>
|
||||
)}
|
||||
{state.newTicket && (
|
||||
<div style={{ marginTop: 12 }}>
|
||||
<div className="flex gap-3 wrap">
|
||||
|
||||
Reference in new issue
Block a user