From 36eb55b81b4ad7236bef8749de85b5751519f22c Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 2 Oct 2026 03:55:04 +0000 Subject: [PATCH] Sidebar: Projekt-Admin entfernt (Admin-Panel abgeschaltet) Co-Authored-By: Claude Opus 5.5 --- src/components/Navbar.jsx | 18 ------------------ src/components/credits/CreditDetail.jsx | 2 +- src/components/offers/OfferForm.jsx | 2 +- src/lib/chatFormat.js | 4 ++-- src/lib/creditFormat.js | 2 +- src/lib/employeeAdminApi.js | 10 ---------- src/lib/format.js | 4 ++-- src/lib/offerFormat.js | 4 ++-- src/lib/storageFormat.js | 2 +- src/styles/chat.css | 2 +- src/styles/global.css | 5 ----- tests/unit/adminFormat.test.mjs | 2 +- 12 files changed, 12 insertions(+), 45 deletions(-) diff --git a/src/components/Navbar.jsx b/src/components/Navbar.jsx index df03618..7ff77e8 100644 --- a/src/components/Navbar.jsx +++ b/src/components/Navbar.jsx @@ -15,13 +15,11 @@ import { IconLogout, IconLayoutSidebarLeftCollapse, IconLayoutSidebarLeftExpand, - IconExternalLink, IconMessages, IconReceiptRefund, IconDiscount, IconMailCog, } from '@tabler/icons-react' -import { openProjectAdmin } from '../lib/employeeAdminApi' import { serverpulsApi } from '../lib/serverpulsApi' import { startsCollapsed } from '../lib/sidebar' import { buildNavLinks } from '../lib/navLinks' @@ -49,7 +47,6 @@ export default function Sidebar() { const navigate = useNavigate() const location = useLocation() const [collapsed, setCollapsed] = useState(() => startsCollapsed()) - const [switching, setSwitching] = useState(false) const [pulseLevel, setPulseLevel] = useState('ok') const counts = useSidebarCounts() @@ -67,11 +64,6 @@ export default function Sidebar() { return () => { dead = true; clearInterval(iv) } }, [isAdmin]) - const handleProjectAdmin = async () => { - setSwitching(true) - await openProjectAdmin() - } - const handleLogout = async () => { await logout() navigate('/login') @@ -139,16 +131,6 @@ export default function Sidebar() { )), ])} - diff --git a/src/components/credits/CreditDetail.jsx b/src/components/credits/CreditDetail.jsx index a187bb4..ef31d20 100644 --- a/src/components/credits/CreditDetail.jsx +++ b/src/components/credits/CreditDetail.jsx @@ -13,7 +13,7 @@ const staffOf = (by) => (by && by !== 'customer' && by !== 'system' ? ` · ${by} const toCents = (value) => Math.round(Number(value) * 100) /** - * Antrag auf Uebernahmegutschrift: Pruefung und Entscheidung wie im frueheren Admin-Panel (public/admin.js 684-906). + * Antrag auf Uebernahmegutschrift: Pruefung und Entscheidung wie im frueheren Admin-Panel. * Waehrend einer Entscheidung sind alle Knoepfe gesperrt (busyRef verhindert auch Doppelklicks vor dem Neuzeichnen). */ export default function CreditDetail({ id, onClose, onChanged, onOpen }) { diff --git a/src/components/offers/OfferForm.jsx b/src/components/offers/OfferForm.jsx index d48cf3c..d50de33 100644 --- a/src/components/offers/OfferForm.jsx +++ b/src/components/offers/OfferForm.jsx @@ -10,7 +10,7 @@ import '../../styles/admin-areas.css' const MONTHS = Array.from({ length: 12 }, (_, i) => i + 1) /** - * "Neues Angebot" wie im frueheren Admin-Panel (public/admin.js 1131-1311). Der Kontext (Abo, offene Angebote, Preise) + * "Neues Angebot" wie im frueheren Admin-Panel. Der Kontext (Abo, offene Angebote, Preise) * wird genau einmal je gewaehltem Kunden geladen; beim Wechsel sofort geleert, spaete Antworten verworfen. Vorschau * und Speichern erst mit dem Kontext des aktuellen Kunden. */ diff --git a/src/lib/chatFormat.js b/src/lib/chatFormat.js index 766f9e4..e0f9ccc 100644 --- a/src/lib/chatFormat.js +++ b/src/lib/chatFormat.js @@ -10,7 +10,7 @@ export function sortChats(chats) { }) } -/** Ergebnis des Mail-Hinweises an den Kunden (K17), Texte wie im Admin-Panel. */ +/** Ergebnis des Mail-Hinweises an den Kunden (K17), Texte wie im frueheren Admin-Panel. */ export function noticeText(notice, time) { if (!notice) return '' if (notice.sent) return `E-Mail-Hinweis an ${notice.to} gesendet (${time})` @@ -30,7 +30,7 @@ export function messageMeta(msg, customerName) { const FULL_REFRESH_MS = 10 * 60 * 1000 export const needsFullRefresh = (lastFullAt, now) => now - lastFullAt >= FULL_REFRESH_MS -/** Eindeutige Beschriftung fuer "Neue Nachricht an Kunde…" wie im Admin-Panel: Name · E-Mail · Kd.-Nr. */ +/** Eindeutige Beschriftung fuer "Neue Nachricht an Kunde…" wie im frueheren Admin-Panel: Name · E-Mail · Kd.-Nr. */ export function customerPickLabel(c) { return [c.name, c.email, c.code ? `Kd.-Nr. ${c.code}` : ''].filter(Boolean).join(' · ') || c.$id } diff --git a/src/lib/creditFormat.js b/src/lib/creditFormat.js index f91c7c5..3025455 100644 --- a/src/lib/creditFormat.js +++ b/src/lib/creditFormat.js @@ -1,6 +1,6 @@ import { fmtDate, formatCents } from './format' -// Uebernahmegutschriften: Texte und Pruefungen wortgleich aus dem Admin-Panel (public/admin.js 535-906). +// Uebernahmegutschriften: Texte und Pruefungen wortgleich aus dem frueheren Admin-Panel des Portals. export const CREDIT_STATUS = { offen: { tone: 'warn', label: 'Zu prüfen' }, diff --git a/src/lib/employeeAdminApi.js b/src/lib/employeeAdminApi.js index 11dc0a8..f4c73fe 100644 --- a/src/lib/employeeAdminApi.js +++ b/src/lib/employeeAdminApi.js @@ -38,13 +38,3 @@ export function updateEmployeeWithLogin(employeeId, payload) { export function deleteEmployeeWithLogin(employeeId) { return adminFetch(`/api/admin/employees/${employeeId}`, { method: 'DELETE' }) } - -/** Wechsel ins Projekt-Admin ohne zweiten Login: Einmal-Link holen und im selben Tab oeffnen. */ -export async function openProjectAdmin() { - try { - const { openUrl } = await adminFetch('/api/admin/switch-link', { method: 'POST', body: {} }) - window.location.assign(openUrl) - } catch { - window.location.assign('https://project.webklar.com/login.html') - } -} diff --git a/src/lib/format.js b/src/lib/format.js index 2423379..1b4c388 100644 --- a/src/lib/format.js +++ b/src/lib/format.js @@ -1,4 +1,4 @@ -// Gemeinsame Formate fuer die Bereiche aus dem Admin-Panel (Gutschriften, Angebote, E-Mail-Speicher). +// Gemeinsame Formate fuer die Bereiche aus dem frueheren Admin-Panel (Gutschriften, Angebote, E-Mail-Speicher). // Deutsche Zeit (Europe/Berlin), Euro wie Intl de-DE. Rein, unter Node testbar. const EURO = new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }) @@ -30,7 +30,7 @@ export function fmtDate(value) { return `${p.day}.${p.month}.${p.year}` } -/** dd.mm.yy, hh:mm (deutsche Zeit) wie im Admin-Panel; leer -> "–" */ +/** dd.mm.yy, hh:mm (deutsche Zeit) wie im frueheren Admin-Panel; leer -> "–" */ export function fmtDateTime(value) { if (!valid(value)) return value ? String(value) : '–' const p = parts(value, { day: '2-digit', month: '2-digit', year: '2-digit', hour: '2-digit', minute: '2-digit' }) diff --git a/src/lib/offerFormat.js b/src/lib/offerFormat.js index 8267dcb..1770b6d 100644 --- a/src/lib/offerFormat.js +++ b/src/lib/offerFormat.js @@ -1,6 +1,6 @@ import { berlinYmd, fmtBerlin, fmtDate, fmtYmd, formatCents, PRODUCT_LABEL } from './format' -// Abo-Angebote: Texte, Rabattende und Formularpruefung wortgleich aus dem Admin-Panel (public/admin.js 984-1317). +// Abo-Angebote: Texte, Rabattende und Formularpruefung wortgleich aus dem frueheren Admin-Panel des Portals. // "today" ist der Kalendertag in Deutschland (YYYY-MM-DD) und fuer Tests injizierbar. export const OFFER_STATUS = { @@ -52,7 +52,7 @@ export function discountLine(o, today = todayBerlin()) { export const isRunning = (ctx, productKey) => Boolean(ctx?.subscription?.active && ctx.subscription.productKey === productKey) /** - * Pruefung und Vorschau des Formulars "Neues Angebot" (admin.js renderOfferPreview). + * Pruefung und Vorschau des Formulars "Neues Angebot" (wie im frueheren Admin-Panel). * -> { errors, running, saveLabel, previewLines }; Speichern nur ohne errors. */ export function evaluateOfferForm(ctx, f, today = todayBerlin()) { diff --git a/src/lib/storageFormat.js b/src/lib/storageFormat.js index 0da1915..6ffe0b3 100644 --- a/src/lib/storageFormat.js +++ b/src/lib/storageFormat.js @@ -1,6 +1,6 @@ import { fmtDate } from './format' -// E-Mail-Speicher (Zusatzspeicher-Aufgaben in konsoleH): Texte wortgleich aus dem Admin-Panel (public/admin.js 908-982). +// E-Mail-Speicher (Zusatzspeicher-Aufgaben in konsoleH): Texte wortgleich aus dem frueheren Admin-Panel des Portals. const GB_INCLUDED = 5 const GB_PER_UNIT = 5 diff --git a/src/styles/chat.css b/src/styles/chat.css index 8c70d06..7e71084 100644 --- a/src/styles/chat.css +++ b/src/styles/chat.css @@ -21,7 +21,7 @@ .woms-chat .chat-bubble.mine { align-self: flex-end; background: var(--accent-soft); border: 1px solid rgba(16, 185, 129, 0.35); } .woms-chat .chat-meta { display: block; margin-top: 4px; font-size: 11.5px; color: var(--text-muted); } .woms-chat .chat-notice { font-size: 12px; } -/* Eingabefeld: Grundstil wie im Admin-Panel (chat-composer.css setzt nur das Layout) */ +/* Eingabefeld: Grundstil wie im frueheren Admin-Panel (chat-composer.css setzt nur das Layout) */ .woms-chat .chat-input-row textarea { resize: none; min-height: 46px; max-height: 130px; padding: 11px 14px; border-radius: 14px; border: 1px solid var(--border); background: var(--surface-2); color: var(--text); font: inherit; line-height: 1.4; diff --git a/src/styles/global.css b/src/styles/global.css index 00e5610..f4c6a19 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -843,11 +843,6 @@ textarea.form-control { } .side-link svg { width: 20px; height: 20px; flex-shrink: 0; } .side-link:hover { background: var(--surface-2); color: var(--text); } -.side-link-button { - background: transparent; border: none; font: inherit; cursor: pointer; - width: calc(100% - 2 * var(--sp-1)); text-align: left; -} -.side-link-button:disabled { opacity: 0.6; cursor: progress; } .side-link-paused, .side-link-paused:hover { opacity: 0.45; cursor: not-allowed; background: transparent; color: var(--text-muted); } .side-link.active { background: var(--accent-soft); color: var(--accent); font-weight: 600; } .side-sublink { padding-left: calc(var(--sp-3) + 18px); font-size: 13.5px; } diff --git a/tests/unit/adminFormat.test.mjs b/tests/unit/adminFormat.test.mjs index 878952c..d5bc0e4 100644 --- a/tests/unit/adminFormat.test.mjs +++ b/tests/unit/adminFormat.test.mjs @@ -2,7 +2,7 @@ import test from 'node:test' import assert from 'node:assert/strict' import { loadModule } from './load.mjs' -// Etappe 3: Texte und Rechnungen aus dem Admin-Panel (public/admin.js), wortgleich ins Ticketsystem uebernommen +// Etappe 3: Texte und Rechnungen aus dem frueheren Admin-Panel des Portals, wortgleich ins Ticketsystem uebernommen const fmt = await loadModule('src/lib/format.js') const credit = await loadModule('src/lib/creditFormat.js') const offer = await loadModule('src/lib/offerFormat.js')