diff --git a/src/pages/ServicesPage.jsx b/src/pages/ServicesPage.jsx
index 1dd5265..32a7f94 100644
--- a/src/pages/ServicesPage.jsx
+++ b/src/pages/ServicesPage.jsx
@@ -1,14 +1,12 @@
import { useState, useEffect, useMemo } from 'react'
-import { Link, useNavigate } from 'react-router-dom'
-import { FaSpinner } from 'react-icons/fa6'
-import { dotColor } from '../lib/previewEnv'
+import { Link } from 'react-router-dom'
import { fetchServices } from '../lib/projectKindsApi'
import { servicesCards } from '../lib/servicesView'
import { ticketPath } from '../lib/ticketRoutes'
+import { previewStateTone } from '../components/projectTones'
import { PageHeader, Card, Button, Badge } from '../components/ui'
export default function ServicesPage() {
- const navigate = useNavigate()
const [data, setData] = useState(null)
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)
@@ -28,59 +26,59 @@ export default function ServicesPage() {
const cards = useMemo(() => servicesCards(data), [data])
- if (loading) return
+ if (loading) return
return (
{error && (
-
- {error}
-
-
+
+
{error}
+
+
+
+
)}
-
- {cards.map((c) => (
-
- {c.description && {c.description}
}
+ {cards.map((c) => (
+
+
+ {c.description &&
{c.description}
}
{c.features.length > 0 && (
-
+
{c.features.map((f) => (
{f.label}{f.statusLabel ? ` · ${f.statusLabel}` : ''}
))}
)}
-
- {c.projects.map((p) => (
-
-
-
- {p.previewState && (
-
- {`Preview: ${p.previewState}`}
-
- )}
- {p.projectName || p.repoFullName}
- {p.features?.analyse === 'active' && Analyse an}
-
-
- {[p.customerName, p.previewUrl && 'Preview'].filter(Boolean).join(' · ') || 'Intern'}
+ {c.projects.length > 0 ? (
+
+ {c.projects.map((p) => (
+
+
+
+ {p.projectName || p.repoFullName}
+ {p.previewState && Preview: {p.previewState}}
+ {p.features?.analyse === 'active' && Analyse an}
+
+
+ {[p.customerName, p.previewUrl && 'Preview'].filter(Boolean).join(' · ') || 'Intern'}
+
+ {(p.woid || c.key === 'missing') && (
+
+ {p.woid && Ticket #{p.woid}}
+ {c.key === 'missing' && Zuordnen}
+
+ )}
- {p.woid &&
Ticket #{p.woid}}
- {c.key === 'missing' && (
-
- )}
-
- ))}
- {c.projects.length === 0 &&
Noch keine Projekte.
}
-
-
- ))}
-
+ ))}
+
+ ) : (
+
Noch keine Projekte.
+ )}
+
+
+ ))}
)
}
diff --git a/src/styles/global.css b/src/styles/global.css
index 04d6790..962de7a 100644
--- a/src/styles/global.css
+++ b/src/styles/global.css
@@ -1188,6 +1188,10 @@ button.list-row:focus-visible { outline-offset: -2px; } /* in .pick-list (Scroll
.assign-step > .seg, .assign-step > .check { align-self: flex-start; }
.page .assign-step .field { margin-bottom: 0; } /* KOMPAT gibt .page .field 12 px unten; hier steht der Abstand der Spalte (P10 loescht beide) */
button.list-row:hover .faint, button.list-row[aria-pressed="true"] .faint { color: var(--text-2); } /* .faint hat auf --bg-hover nur 2,9:1 (Muster: .table tr.row:hover .faint) */
+/* ---------- Services ---------- */
+/* Beschreibung, Funktions-Badges und Zeilen einer Art als Spalte mit Abstand (der Reset setzt jeden Aussenabstand auf 0); auch Fehlermeldung plus Knopf */
+.services-stack { display: flex; flex-direction: column; gap: 12px; }
+.services-stack > .pick-empty { padding: 0; } /* der Abstand kommt aus gap */
/* ===== ENDE Projekte (P5) ===== */
/* ===== KOMPAT (bis P10) ===== */