diff --git a/src/lib/customerTabs.js b/src/lib/customerTabs.js new file mode 100644 index 0000000..e9056b7 --- /dev/null +++ b/src/lib/customerTabs.js @@ -0,0 +1,19 @@ +// Reiter der Kundenansicht (rein, ohne React; unter Node testbar). „Rechnungen“ ruft die Finanzen-API des Portals auf, +// die nur Admins freigibt: für alle anderen gibt es den Reiter nicht. + +const BASE_TABS = [ + { id: 'overview', label: 'Uebersicht' }, + { id: 'tickets', label: 'Tickets' }, + { id: 'invoices', label: 'Rechnungen', adminOnly: true }, + { id: 'projects', label: 'Projekte' }, +] + +/** Reiter für Tabs: [{ id, label }]; „Rechnungen“ nur für Admins. */ +export function customerTabs(isAdmin) { + return BASE_TABS.filter((t) => !t.adminOnly || isAdmin === true).map(({ id, label }) => ({ id, label })) +} + +/** Der Reiter, der tatsächlich gezeigt wird: ein nicht (mehr) erlaubter oder unbekannter Reiter fällt auf „Übersicht“ zurück. */ +export function resolveCustomerTab(tab, isAdmin) { + return customerTabs(isAdmin).some((t) => t.id === tab) ? tab : 'overview' +} diff --git a/src/lib/financeView.js b/src/lib/financeView.js index 5b2f722..4775d23 100644 --- a/src/lib/financeView.js +++ b/src/lib/financeView.js @@ -748,7 +748,7 @@ export function resolveCustomerText(options, input) { /** * Reiter „Rechnungen“ am Kunden: { ok: true } oder { ok: false, title, hint } (Grund nach canInvoice plus ein Satz, - * was zu tun ist). Der Reiter ist für jeden Kunden sichtbar; ohne ok zeigt er statt der Liste diesen Hinweis. + * was zu tun ist). Der Reiter ist für Admins bei jedem Kunden sichtbar; ohne ok zeigt er statt der Liste diesen Hinweis. */ export function customerInvoicesGate(customer) { const check = canInvoice(customer) @@ -776,7 +776,7 @@ export function customerInvoicesGate(customer) { // --- Buchungen (Block 7) ----------------------------------------------------------------------------------- -const RANK ={ hoch: 0, mittel: 1, niedrig: 2 } +const RANK = { hoch: 0, mittel: 1, niedrig: 2 } const dayOf = (tx) => text(tx.bookingDate) || text(tx.valueDate) /** Buchungen neueste zuerst (Buchungsdatum, sonst Wertstellung); gleiche Tage behalten die Reihenfolge des Servers. */ diff --git a/src/pages/CustomerDetailPage.jsx b/src/pages/CustomerDetailPage.jsx index 58be87b..0e7abf0 100644 --- a/src/pages/CustomerDetailPage.jsx +++ b/src/pages/CustomerDetailPage.jsx @@ -10,17 +10,11 @@ import CopyableCredential, { getCustomerPortalPassword } from '../components/Cop import { updateCustomerWithPortalAccess, deleteCustomerWithPortalAccess } from '../lib/customerAdminApi' import { useAuth } from '../context/AuthContext' import { useWebsiteProjects } from '../hooks/useWebsiteProjects' +import { customerTabs, resolveCustomerTab } from '../lib/customerTabs' import { customerStage, isArchived, isInvoiceReady, setCustomerArchived, upgradeToCustomer } from '../lib/leads' const PORTAL_URL = 'https://project.webklar.com' -const TABS = [ - { id: 'overview', label: 'Uebersicht' }, - { id: 'tickets', label: 'Tickets' }, - { id: 'invoices', label: 'Rechnungen' }, - { id: 'projects', label: 'Projekte' }, -] - export default function CustomerDetailPage() { const { id } = useParams() const [customer, setCustomer] = useState(null) @@ -48,6 +42,8 @@ export default function CustomerDetailPage() { if (error || !customer) return