'use client' /** * Responsive DevOps Pipeline Sidebar (Mobile FAB + Drawer) * * Extracted from DevOpsPipelineSidebar.tsx. * Desktop (xl+): Fixierte Sidebar rechts * Mobile/Tablet: Floating Action Button unten rechts, oeffnet Drawer */ import Link from 'next/link' import { useState, useEffect } from 'react' import type { DevOpsPipelineSidebarResponsiveProps, PipelineLiveStatus, } from '@/types/infrastructure-modules' import { DEVOPS_PIPELINE_MODULES } from '@/types/infrastructure-modules' import { DevOpsPipelineSidebar } from './DevOpsPipelineSidebar' // Server/Pipeline Icon fuer Header const ServerIcon = () => ( ) // Play Icon fuer Quick Action const PlayIcon = () => ( ) // Inline ToolIcon (duplicated to avoid circular imports) const ToolIcon = ({ id }: { id: string }) => { const icons: Record = { 'ci-cd': , 'tests': , 'sbom': , 'security': , } return icons[id] || null } interface StatusBadgeProps { count: number type: 'backlog' | 'security' | 'running' } function StatusBadge({ count, type }: StatusBadgeProps) { if (count === 0) return null const colors = { backlog: 'bg-amber-500', security: 'bg-red-500', running: 'bg-green-500 animate-pulse', } return ( {count} ) } function usePipelineLiveStatus(): PipelineLiveStatus | null { const [status, setStatus] = useState(null) useEffect(() => { /* placeholder for live status fetch */ }, []) return status } export function DevOpsPipelineSidebarResponsive({ currentTool, compact = false, className = '', fabPosition = 'bottom-right', }: DevOpsPipelineSidebarResponsiveProps) { const [isMobileOpen, setIsMobileOpen] = useState(false) const liveStatus = usePipelineLiveStatus() useEffect(() => { const handleEscape = (e: KeyboardEvent) => { if (e.key === 'Escape') setIsMobileOpen(false) } window.addEventListener('keydown', handleEscape) return () => window.removeEventListener('keydown', handleEscape) }, []) useEffect(() => { if (isMobileOpen) { document.body.style.overflow = 'hidden' } else { document.body.style.overflow = '' } return () => { document.body.style.overflow = '' } }, [isMobileOpen]) const fabPositionClasses = fabPosition === 'bottom-right' ? 'right-4 bottom-20' : 'left-4 bottom-20' const totalBadgeCount = liveStatus ? liveStatus.backlogCount + liveStatus.securityFindingsCount : 0 return ( <> {/* Desktop: Fixed Sidebar */}
{/* Mobile/Tablet: FAB */} {/* Mobile/Tablet: Drawer Overlay */} {isMobileOpen && (
setIsMobileOpen(false)} />
DevOps Pipeline {liveStatus?.isRunning && }
{DEVOPS_PIPELINE_MODULES.map((tool) => ( setIsMobileOpen(false)} className={`flex items-center gap-3 px-4 py-3 rounded-xl transition-all ${currentTool === tool.id ? 'bg-orange-100 dark:bg-orange-900/30 text-orange-700 dark:text-orange-300 font-medium shadow-sm' : 'text-slate-600 dark:text-slate-400 hover:bg-slate-100 dark:hover:bg-gray-800'}`}>
{tool.name}
{tool.description}
{tool.id === 'tests' && liveStatus && } {tool.id === 'security' && liveStatus && } {currentTool === tool.id && } ))}
Pipeline Flow
{[{e:'📝',l:'Code'},{e:'🏗️',l:'Build'},{e:'✅',l:'Test'},{e:'🚀',l:'Deploy'}].map((s,i,a)=>( {s.e}{s.l} {i} ))}
setIsMobileOpen(false)} className="flex items-center gap-2 px-3 py-2 text-sm text-orange-600 dark:text-orange-400 hover:bg-orange-50 dark:hover:bg-orange-900/20 rounded-lg transition-colors"> Zur Infrastructure-Uebersicht
)} ) }