@bricks2k/governance 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/components/dashboard/DashboardLayout.jsx","../src/components/widgets/MetricCard.jsx","../src/components/widgets/HealthScore.jsx","../src/components/widgets/TechStackList.jsx","../src/utils/governanceParser.js","../src/components/widgets/RecentActivityFeed.jsx","../src/components/widgets/QuickActionsGrid.jsx","../src/components/dashboard/OverviewTab.jsx","../src/utils/governanceData.js","../src/components/techdebt/DebtStats.jsx","../src/components/techdebt/DebtFilters.jsx","../src/components/techdebt/SeverityBadge.jsx","../src/utils/governanceUtils.js","../src/components/techdebt/DebtCard.jsx","../src/components/dashboard/TechDebtTab.jsx","../src/components/backlog/BacklogStats.jsx","../src/components/backlog/BacklogFilters.jsx","../src/components/backlog/CategoryBadge.jsx","../src/components/backlog/BacklogItem.jsx","../src/components/dashboard/BacklogTab.jsx","../src/components/dashboard/MarkdownViewer.jsx","../src/components/logs/LogEntry.jsx","../src/components/logs/LogTimeline.jsx","../src/components/logs/LogFilters.jsx","../src/components/dashboard/LogsTab.jsx","../src/components/dashboard/ArchitectureTab.jsx","../src/contexts/GovernanceContext.jsx","../src/components/supabase/ServiceCard.jsx","../src/components/supabase/DevToolsSection.jsx","../src/components/supabase/CredentialField.jsx","../src/components/supabase/AuthKeysSection.jsx","../src/components/supabase/HealthStatusSection.jsx","../src/components/supabase/APIsSection.jsx","../src/components/supabase/DatabaseSection.jsx","../src/components/dashboard/SupabaseTab.jsx","../src/components/dashboard/AISettingsTab.jsx","../src/components/dashboard/AIConsumptionTab.jsx","../src/components/dashboard/DevAssistantTab.jsx"],"sourcesContent":["import { useNavigate } from 'react-router-dom';\r\nimport { ChevronLeft, RefreshCw, Check } from 'lucide-react';\r\n\r\n/**\r\n * Layout com Tabs para o Dashboard de Governança\r\n *\r\n * @param {Array} tabs - Lista de tabs\r\n * @param {string} activeTab - Tab ativo\r\n * @param {Function} onTabChange - Callback para mudar tab\r\n * @param {Function} onRefresh - Callback para refresh de dados (opcional)\r\n * @param {boolean} isRefreshing - Estado de loading do refresh (opcional)\r\n * @param {boolean} refreshSuccess - Estado de sucesso do refresh (opcional)\r\n * @param {ReactNode} children - Conteúdo da tab ativa\r\n */\r\nexport default function DashboardLayout({ tabs, activeTab, onTabChange, onRefresh, isRefreshing, refreshSuccess, children }) {\r\n const navigate = useNavigate();\r\n\r\n return (\r\n <div className=\"min-h-screen bg-slate-900\">\r\n {/* Header */}\r\n <header className=\"bg-slate-800 border-b border-slate-700 sticky top-0 z-30\">\r\n <div className=\"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8\">\r\n <div className=\"flex items-center justify-between h-16\">\r\n <div className=\"flex items-center gap-4\">\r\n <button\r\n onClick={() => navigate('/')}\r\n className=\"p-2 text-slate-400 hover:text-slate-200 hover:bg-slate-700 rounded-lg transition-colors\"\r\n >\r\n <ChevronLeft className=\"w-5 h-5\" />\r\n </button>\r\n <h1 className=\"text-xl font-bold text-slate-100\">\r\n 🛠️ Dev Dashboard\r\n </h1>\r\n </div>\r\n \r\n {onRefresh && (\r\n <button\r\n onClick={onRefresh}\r\n disabled={isRefreshing}\r\n className={`\r\n flex items-center gap-2 px-4 py-2 rounded-lg font-medium text-sm\r\n transition-colors duration-200\r\n ${refreshSuccess\r\n ? 'bg-green-600 text-white'\r\n : 'bg-blue-600 text-white hover:bg-blue-700'\r\n }\r\n ${isRefreshing ? 'opacity-50 cursor-not-allowed' : ''}\r\n `}\r\n >\r\n {refreshSuccess ? (\r\n <>\r\n <Check className=\"w-4 h-4\" />\r\n Atualizado!\r\n </>\r\n ) : (\r\n <>\r\n <RefreshCw className={`w-4 h-4 ${isRefreshing ? 'animate-spin' : ''}`} />\r\n {isRefreshing ? 'Atualizando...' : 'Atualizar Dados'}\r\n </>\r\n )}\r\n </button>\r\n )}\r\n </div>\r\n\r\n {/* Tabs */}\r\n <div className=\"flex gap-1 -mb-px overflow-x-auto scrollbar-thin\">\r\n {tabs.map(tab => (\r\n <button\r\n key={tab.id}\r\n onClick={() => onTabChange(tab.id)}\r\n className={`px-4 py-3 text-sm font-medium whitespace-nowrap transition-colors border-b-2 ${\r\n activeTab === tab.id\r\n ? 'border-emerald-500 text-emerald-400'\r\n : 'border-transparent text-slate-400 hover:text-slate-300 hover:border-slate-600'\r\n }`}\r\n >\r\n <span className=\"mr-2\">{tab.icon}</span>\r\n {tab.label}\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n </header>\r\n\r\n {/* Content */}\r\n <main className=\"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8\">\r\n {children}\r\n </main>\r\n </div>\r\n );\r\n}\r\n","/**\r\n * Card de Métrica\r\n * Widget reutilizável para exibir métricas do projeto\r\n * \r\n * @param {string} title - Título da métrica\r\n * @param {number} value - Valor principal\r\n * @param {string} subtitle - Texto secundário\r\n * @param {string} icon - Emoji do ícone\r\n * @param {string} trend - Tendência (success, danger, warning, neutral)\r\n */\r\nexport default function MetricCard({ title, value, subtitle, icon, trend = 'neutral' }) {\r\n const trendColors = {\r\n success: 'text-emerald-400',\r\n danger: 'text-red-400',\r\n warning: 'text-amber-400',\r\n neutral: 'text-slate-400'\r\n };\r\n\r\n return (\r\n <div className=\"bg-slate-800 border border-slate-700 rounded-lg p-6\">\r\n <div className=\"flex items-start justify-between mb-4\">\r\n <span className=\"text-3xl\">{icon}</span>\r\n <span className={`text-2xl font-bold ${trendColors[trend]}`}>\r\n {value}\r\n </span>\r\n </div>\r\n <h3 className=\"text-slate-300 font-medium mb-1\">{title}</h3>\r\n <p className=\"text-sm text-slate-500\">{subtitle}</p>\r\n </div>\r\n );\r\n}\r\n","/**\r\n * Health Score Widget\r\n * Exibe o score de saúde do projeto com círculo SVG\r\n * \r\n * @param {number} score - Score de 0-100\r\n */\r\nexport default function HealthScore({ score }) {\r\n const getScoreColor = (score) => {\r\n if (score >= 80) return { bg: 'bg-emerald-500', text: 'text-emerald-400' };\r\n if (score >= 60) return { bg: 'bg-amber-500', text: 'text-amber-400' };\r\n return { bg: 'bg-red-500', text: 'text-red-400' };\r\n };\r\n\r\n const colors = getScoreColor(score);\r\n\r\n return (\r\n <div className=\"bg-gradient-to-r from-slate-800 to-slate-700 border border-slate-600 rounded-lg p-8\">\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <h3 className=\"text-lg text-slate-400 mb-2\">Project Health Score</h3>\r\n <div className=\"flex items-baseline gap-2\">\r\n <span className={`text-6xl font-bold ${colors.text}`}>\r\n {score}\r\n </span>\r\n <span className=\"text-2xl text-slate-500\">/100</span>\r\n </div>\r\n <p className=\"text-sm text-slate-500 mt-2\">\r\n Baseado em débitos técnicos, cobertura de testes e docs\r\n </p>\r\n </div>\r\n \r\n <div className=\"relative w-32 h-32\">\r\n <svg className=\"transform -rotate-90\" viewBox=\"0 0 120 120\">\r\n {/* Background circle */}\r\n <circle\r\n cx=\"60\"\r\n cy=\"60\"\r\n r=\"50\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"10\"\r\n fill=\"none\"\r\n className=\"text-slate-700\"\r\n />\r\n {/* Progress circle */}\r\n <circle\r\n cx=\"60\"\r\n cy=\"60\"\r\n r=\"50\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"10\"\r\n fill=\"none\"\r\n strokeDasharray={`${score * 3.14} 314`}\r\n className={colors.bg.replace('bg-', 'text-')}\r\n strokeLinecap=\"round\"\r\n />\r\n </svg>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","/**\r\n * Tech Stack List\r\n * Lista das tecnologias do projeto\r\n * \r\n * @param {Object} stack - Objeto com tecnologias { frontend, backend, database, styling }\r\n */\r\nexport default function TechStackList({ stack }) {\r\n const items = [\r\n { label: 'Frontend', value: stack.frontend, icon: '⚛️' },\r\n { label: 'Backend', value: stack.backend, icon: '🔥' },\r\n { label: 'Database', value: stack.database, icon: '🗄️' },\r\n { label: 'Styling', value: stack.styling, icon: '🎨' }\r\n ];\r\n\r\n return (\r\n <div className=\"bg-slate-800 border border-slate-700 rounded-lg p-6\">\r\n <h3 className=\"text-lg font-semibold text-slate-100 mb-4\">Tech Stack</h3>\r\n <div className=\"space-y-3\">\r\n {items.map((item, index) => (\r\n <div key={index} className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-3\">\r\n <span className=\"text-2xl\">{item.icon}</span>\r\n <span className=\"text-sm text-slate-400\">{item.label}</span>\r\n </div>\r\n <span className=\"text-sm font-medium text-slate-200\">{item.value}</span>\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n );\r\n}\r\n","/**\r\n * Governance Parser\r\n * Utilitários para parse de arquivos Markdown de governança:\r\n * - TECHNICAL_DEBT_REGISTRY.md\r\n * - BACKLOG_REGISTRY.md\r\n * - .logs/*.log.md\r\n * - docs/plans/*.md\r\n * \r\n * @author Nexus Code\r\n * @date 2026-01-12\r\n */\r\n\r\n/**\r\n * Parse Tech Debt Registry\r\n * @param {string} markdownContent - Conteúdo do TECHNICAL_DEBT_REGISTRY.md\r\n * @returns {Object} { debts: Array, stats: Object }\r\n */\r\nexport function parseTechDebtRegistry(markdownContent) {\r\n // Split por \\r\\n ou \\n e trim cada linha (cross-platform)\r\n const lines = markdownContent.split(/\\r?\\n/).map(l => l.trimEnd());\r\n const debts = [];\r\n \r\n lines.forEach(line => {\r\n // Verificar se linha começa com | TD-XXX\r\n const trimmed = line.trim();\r\n if (trimmed.startsWith('| TD-')) {\r\n const cols = line.split('|').map(s => s.trim()).filter(Boolean);\r\n \r\n // Deve ter pelo menos 8 colunas (ID, Desc, Severity, Trigger, Location, Owner, Status, Created)\r\n if (cols.length >= 8) {\r\n debts.push({\r\n id: cols[0],\r\n description: cols[1],\r\n severity: cols[2],\r\n trigger: cols[3],\r\n location: cols[4],\r\n owner: cols[5],\r\n status: cols[6],\r\n created: cols[7]\r\n });\r\n }\r\n }\r\n });\r\n \r\n // Calcular estatísticas\r\n const stats = {\r\n total: debts.length,\r\n pending: debts.filter(d => d.status.includes('Pendente') || d.status.includes('⏳')).length,\r\n critical: debts.filter(d => d.severity.includes('🔴') || d.severity.includes('Crítico')).length,\r\n high: debts.filter(d => d.severity.includes('🟠') || d.severity.includes('Alto')).length,\r\n medium: debts.filter(d => d.severity.includes('🟡') || d.severity.includes('Médio')).length,\r\n low: debts.filter(d => d.severity.includes('🟢') || d.severity.includes('Baixo')).length\r\n };\r\n \r\n return { debts, stats };\r\n}\r\n\r\n/**\r\n * Parse Backlog Registry\r\n * @param {string} markdownContent - Conteúdo do BACKLOG_REGISTRY.md\r\n * @returns {Object} { items: Array, stats: Object }\r\n */\r\nexport function parseBacklogRegistry(markdownContent) {\r\n // Split por \\r\\n ou \\n e trim cada linha (cross-platform)\r\n const lines = markdownContent.split(/\\r?\\n/).map(l => l.trimEnd());\r\n const items = [];\r\n \r\n lines.forEach(line => {\r\n // Verificar se linha começa com | BL-XXX\r\n const trimmed = line.trim();\r\n if (trimmed.startsWith('| BL-')) {\r\n const cols = line.split('|').map(s => s.trim()).filter(Boolean);\r\n \r\n // Deve ter pelo menos 7 colunas (ID, Title, Category, Status, Owner, Estimate, Created)\r\n if (cols.length >= 7) {\r\n items.push({\r\n id: cols[0],\r\n title: cols[1],\r\n category: cols[2],\r\n status: cols[3],\r\n owner: cols[4],\r\n estimate: cols[5],\r\n created: cols[6]\r\n });\r\n }\r\n }\r\n });\r\n \r\n // Calcular estatísticas\r\n const stats = {\r\n total: items.length,\r\n highPriority: items.filter(() => markdownContent.includes('🔴 Alta Prioridade')).length,\r\n mediumPriority: items.filter(() => markdownContent.includes('🟡 Média Prioridade')).length,\r\n lowPriority: items.filter(() => markdownContent.includes('🟢 Baixa Prioridade')).length,\r\n backlog: items.filter(i => i.status.includes('📋')).length,\r\n planned: items.filter(i => i.status.includes('📅')).length,\r\n doing: items.filter(i => i.status.includes('🚧')).length,\r\n done: items.filter(i => i.status.includes('✅')).length\r\n };\r\n \r\n return { items, stats };\r\n}\r\n\r\n/**\r\n * Parse Architecture Log\r\n * @param {string} markdownContent - Conteúdo do architecture.log.md\r\n * @returns {Array} Log entries\r\n */\r\nexport function parseArchitectureLog(markdownContent) {\r\n const entries = [];\r\n // Split por \\r\\n ou \\n e trim cada linha para remover \\r residual\r\n const lines = markdownContent.split(/\\r?\\n/).map(l => l.trimEnd());\r\n \r\n let currentEntry = null;\r\n let contentLines = [];\r\n \r\n lines.forEach((line) => {\r\n // Detectar início de nova entrada: # YYYY-MM-DD...\r\n const headerMatch = line.match(/^#\\s+(\\d{4}-\\d{2}-\\d{2}T[\\d:.]+Z):\\s*(.+)$/);\r\n \r\n if (headerMatch) {\r\n // Salvar entrada anterior\r\n if (currentEntry) {\r\n currentEntry.content = contentLines.join('\\n');\r\n entries.push(currentEntry);\r\n }\r\n \r\n // Iniciar nova entrada\r\n currentEntry = {\r\n timestamp: headerMatch[1],\r\n title: headerMatch[2].trim(),\r\n content: '',\r\n module: '',\r\n type: '',\r\n author: ''\r\n };\r\n contentLines = [];\r\n } else if (currentEntry && line.trim() !== '' && !line.includes('<!-- ') && line !== '---') {\r\n // Extrair metadados das linhas\r\n if (line.includes('**Módulo:**')) {\r\n currentEntry.module = line.split('**Módulo:**')[1]?.trim().replace(/^-\\s*/, '') || '';\r\n } else if (line.includes('**Tipo:**')) {\r\n currentEntry.type = line.split('**Tipo:**')[1]?.trim().replace(/^-\\s*/, '') || '';\r\n } else if (line.includes('**Responsável:**')) {\r\n currentEntry.author = line.split('**Responsável:**')[1]?.trim().replace(/^-\\s*/, '') || '';\r\n }\r\n \r\n // Acumular conteúdo (exceto comentários HTML e separadores)\r\n contentLines.push(line);\r\n }\r\n });\r\n \r\n // Adicionar última entrada\r\n if (currentEntry) {\r\n currentEntry.content = contentLines.join('\\n');\r\n entries.push(currentEntry);\r\n }\r\n \r\n return entries;\r\n}\r\n\r\n/**\r\n * Calcular Health Score do projeto\r\n * @param {Object} techDebtStats\r\n * @param {Object} backlogStats\r\n * @returns {number} Score de 0-100\r\n */\r\nexport function calculateHealthScore(techDebtStats, backlogStats) {\r\n let score = 100;\r\n \r\n // Penalidade por débitos técnicos críticos\r\n score -= techDebtStats.critical * 10;\r\n \r\n // Penalidade por débitos altos\r\n score -= techDebtStats.high * 5;\r\n \r\n // Penalidade por total de débitos\r\n score -= techDebtStats.pending * 2;\r\n \r\n // Bônus por ter backlog organizado\r\n if (backlogStats.total > 0) {\r\n score += 5;\r\n }\r\n \r\n // Garantir range 0-100\r\n return Math.max(0, Math.min(100, score));\r\n}\r\n\r\n/**\r\n * Obter ícone de categoria de backlog\r\n * @param {string} category\r\n * @returns {string} Emoji\r\n */\r\nexport function getCategoryIcon(category) {\r\n if (category.includes('✨') || category.includes('Feature')) return '✨';\r\n if (category.includes('⚡') || category.includes('Improvement')) return '⚡';\r\n if (category.includes('🔬') || category.includes('Research')) return '🔬';\r\n if (category.includes('🔗') || category.includes('Integration')) return '🔗';\r\n if (category.includes('🎨') || category.includes('UI/UX')) return '🎨';\r\n return '📦';\r\n}\r\n\r\n/**\r\n * Obter ícone de severidade de tech debt\r\n * @param {string} severity\r\n * @returns {string} Emoji\r\n */\r\nexport function getSeverityIcon(severity) {\r\n if (severity.includes('🔴') || severity.includes('Crítico')) return '🔴';\r\n if (severity.includes('🟠') || severity.includes('Alto')) return '🟠';\r\n if (severity.includes('🟡') || severity.includes('Médio')) return '🟡';\r\n if (severity.includes('🟢') || severity.includes('Baixo')) return '🟢';\r\n return '⚪';\r\n}\r\n\r\n/**\r\n * Obter nome legível de severidade\r\n * @param {string} severity\r\n * @returns {string}\r\n */\r\nexport function getSeverityName(severity) {\r\n if (severity.includes('🔴') || severity.includes('Crítico')) return 'Crítico';\r\n if (severity.includes('🟠') || severity.includes('Alto')) return 'Alto';\r\n if (severity.includes('🟡') || severity.includes('Médio')) return 'Médio';\r\n if (severity.includes('🟢') || severity.includes('Baixo')) return 'Baixo';\r\n return 'Desconhecido';\r\n}\r\n\r\n/**\r\n * Obter cor Tailwind por severidade\r\n * @param {string} severity\r\n * @returns {string} Classe Tailwind\r\n */\r\nexport function getSeverityColor(severity) {\r\n if (severity.includes('🔴') || severity.includes('Crítico')) return 'bg-red-500/20 text-red-400 border-red-500/20';\r\n if (severity.includes('🟠') || severity.includes('Alto')) return 'bg-orange-500/20 text-orange-400 border-orange-500/20';\r\n if (severity.includes('🟡') || severity.includes('Médio')) return 'bg-amber-500/20 text-amber-400 border-amber-500/20';\r\n if (severity.includes('🟢') || severity.includes('Baixo')) return 'bg-emerald-500/20 text-emerald-400 border-emerald-500/20';\r\n return 'bg-slate-700 text-slate-400';\r\n}\r\n\r\n/**\r\n * Parse PLANs de docs/plans/*.md\r\n * @param {string} markdownContent - Conteúdo de um PLAN\r\n * @param {string} filename - Nome do arquivo\r\n * @returns {Object} PLAN parseado\r\n */\r\nexport function parsePlan(markdownContent, filename) {\r\n // Split por \\r\\n ou \\n e trim cada linha (cross-platform)\r\n const lines = markdownContent.split(/\\r?\\n/).map(l => l.trimEnd());\r\n \r\n // Extrair frontmatter (primeiras linhas com >)\r\n const frontmatter = {};\r\n let contentStart = 0;\r\n \r\n for (let i = 0; i < lines.length; i++) {\r\n const line = lines[i];\r\n if (line.startsWith('> **')) {\r\n const match = line.match(/\\*\\*(.+?):\\*\\*\\s*(.+)/);\r\n if (match) {\r\n frontmatter[match[1]] = match[2].trim();\r\n }\r\n } else if (line.trim() === '---') {\r\n contentStart = i + 1;\r\n break;\r\n }\r\n }\r\n \r\n // Contar tarefas (checkboxes)\r\n let totalTasks = 0;\r\n let completedTasks = 0;\r\n \r\n lines.forEach(line => {\r\n if (line.includes('- [ ]')) totalTasks++;\r\n if (line.includes('- [x]') || line.includes('- [X]')) {\r\n totalTasks++;\r\n completedTasks++;\r\n }\r\n });\r\n \r\n return {\r\n filename,\r\n title: frontmatter.Contexto || filename.replace('PLAN_', '').replace('.md', ''),\r\n status: frontmatter.Status || '📋 Proposta',\r\n author: frontmatter.Autor || 'Desconhecido',\r\n date: frontmatter.Data || '',\r\n priority: frontmatter.Prioridade || '🟡 Média',\r\n totalTasks,\r\n completedTasks,\r\n progress: totalTasks > 0 ? Math.round((completedTasks / totalTasks) * 100) : 0,\r\n content: lines.slice(contentStart).join('\\n')\r\n };\r\n}\r\n\r\n/**\r\n * Parse Decisions Log\r\n * @param {string} markdownContent - Conteúdo do decisions.log.md\r\n * @returns {Array} Decision entries\r\n */\r\nexport function parseDecisionsLog(markdownContent) {\r\n const entries = [];\r\n // Split por \\r\\n ou \\n e trim cada linha para remover \\r residual\r\n const lines = markdownContent.split(/\\r?\\n/).map(l => l.trimEnd());\r\n let currentEntry = null;\r\n let contentLines = [];\r\n \r\n lines.forEach((line) => {\r\n const headerMatch = line.match(/^#\\s+(\\d{4}-\\d{2}-\\d{2}T[\\d:.]+Z):\\s*(.+)$/);\r\n \r\n if (headerMatch) {\r\n // Salvar entrada anterior\r\n if (currentEntry) {\r\n currentEntry.content = contentLines.join('\\n');\r\n entries.push(currentEntry);\r\n }\r\n \r\n // Iniciar nova entrada\r\n currentEntry = {\r\n timestamp: headerMatch[1],\r\n title: headerMatch[2].trim(),\r\n content: '',\r\n type: 'decision',\r\n context: '',\r\n decision: '',\r\n alternatives: [],\r\n consequences: '',\r\n author: ''\r\n };\r\n contentLines = [];\r\n } else if (currentEntry && line.trim() !== '' && !line.includes('<!-- ') && line !== '---') {\r\n // Extrair metadados das linhas\r\n if (line.includes('**Tipo:**')) {\r\n currentEntry.type = line.split('**Tipo:**')[1]?.trim().replace(/^-\\s*/, '') || 'decision';\r\n } else if (line.includes('**Contexto:**')) {\r\n currentEntry.context = line.split('**Contexto:**')[1]?.trim().replace(/^-\\s*/, '') || '';\r\n } else if (line.includes('**Decisão:**')) {\r\n currentEntry.decision = line.split('**Decisão:**')[1]?.trim().replace(/^-\\s*/, '') || '';\r\n } else if (line.includes('**Responsável:**')) {\r\n currentEntry.author = line.split('**Responsável:**')[1]?.trim().replace(/^-\\s*/, '') || '';\r\n }\r\n \r\n // Acumular conteúdo\r\n contentLines.push(line);\r\n }\r\n });\r\n \r\n // Adicionar última entrada\r\n if (currentEntry) {\r\n currentEntry.content = contentLines.join('\\n');\r\n entries.push(currentEntry);\r\n }\r\n \r\n return entries;\r\n}\r\n\r\n/**\r\n * Parse múltiplos logs e mesclar cronologicamente\r\n * @param {Object} logsContent - { architecture: string, decisions: string, ... }\r\n * @returns {Array} Todas as entradas mescladas e ordenadas\r\n */\r\nexport function parseAllLogs(logsContent) {\r\n const allEntries = [];\r\n \r\n if (logsContent.architecture) {\r\n const archEntries = parseArchitectureLog(logsContent.architecture);\r\n allEntries.push(...archEntries.map(e => ({ ...e, logType: 'architecture', icon: '🏗️' })));\r\n }\r\n \r\n if (logsContent.decisions) {\r\n const decEntries = parseDecisionsLog(logsContent.decisions);\r\n allEntries.push(...decEntries.map(e => ({ ...e, logType: 'decisions', icon: '📝' })));\r\n }\r\n \r\n // Ordenar por timestamp (mais recente primeiro)\r\n allEntries.sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp));\r\n \r\n return allEntries;\r\n}\r\n\r\n/**\r\n * Obter cor Tailwind por prioridade de PLAN\r\n * @param {string} priority\r\n * @returns {string} Classe Tailwind\r\n */\r\nexport function getPriorityColor(priority) {\r\n if (priority.includes('🔴') || priority.includes('Alta')) return 'bg-red-500/20 text-red-400 border-red-500/20';\r\n if (priority.includes('🟡') || priority.includes('Média')) return 'bg-amber-500/20 text-amber-400 border-amber-500/20';\r\n if (priority.includes('🟢') || priority.includes('Baixa')) return 'bg-emerald-500/20 text-emerald-400 border-emerald-500/20';\r\n return 'bg-slate-700 text-slate-400';\r\n}\r\n\r\n/**\r\n * Obter cor Tailwind por status de backlog\r\n * @param {string} status\r\n * @returns {string} Classe Tailwind\r\n */\r\nexport function getStatusColor(status) {\r\n if (status.includes('📋')) return 'bg-slate-600 text-slate-300';\r\n if (status.includes('📅')) return 'bg-blue-600 text-blue-200';\r\n if (status.includes('🚧')) return 'bg-amber-600 text-amber-200';\r\n if (status.includes('✅')) return 'bg-emerald-600 text-emerald-200';\r\n return 'bg-slate-700 text-slate-400';\r\n}\r\n\r\n/**\r\n * Formatar timestamp para legível\r\n * @param {string} timestamp - ISO 8601\r\n * @returns {string} Data formatada\r\n */\r\nexport function formatTimestamp(timestamp) {\r\n try {\r\n const date = new Date(timestamp);\r\n return date.toLocaleDateString('pt-BR', {\r\n year: 'numeric',\r\n month: 'short',\r\n day: 'numeric',\r\n hour: '2-digit',\r\n minute: '2-digit'\r\n });\r\n } catch {\r\n return timestamp;\r\n }\r\n}\r\n","import { formatTimestamp } from '../../utils/governanceParser';\r\n\r\n/**\r\n * Recent Activity Feed\r\n * Feed das últimas atividades (logs)\r\n * \r\n * @param {Array} activities - Array de log entries\r\n */\r\nexport default function RecentActivityFeed({ activities }) {\r\n if (!activities || activities.length === 0) {\r\n return (\r\n <div className=\"bg-slate-800 border border-slate-700 rounded-lg p-6\">\r\n <h3 className=\"text-lg font-semibold text-slate-100 mb-4\">Atividades Recentes</h3>\r\n <p className=\"text-sm text-slate-500\">Nenhuma atividade registrada</p>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"bg-slate-800 border border-slate-700 rounded-lg p-6\">\r\n <h3 className=\"text-lg font-semibold text-slate-100 mb-4\">Atividades Recentes</h3>\r\n <div className=\"space-y-4\">\r\n {activities.slice(0, 5).map((activity, index) => (\r\n <div key={index} className=\"flex gap-3 border-b border-slate-700 pb-3 last:border-0 last:pb-0\">\r\n <div className=\"flex-shrink-0\">\r\n <span className=\"text-xl\">{activity.icon}</span>\r\n </div>\r\n <div className=\"flex-1 min-w-0\">\r\n <p className=\"text-sm font-medium text-slate-200 truncate\">\r\n {activity.title}\r\n </p>\r\n <p className=\"text-xs text-slate-500 mt-1\">\r\n {formatTimestamp(activity.timestamp)}\r\n </p>\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { FileText, GitBranch, AlertTriangle, Target } from 'lucide-react';\r\n\r\n/**\r\n * Quick Actions Grid\r\n * Grid de ações rápidas para navegação\r\n *\r\n * @param {Function} onTabChange - Callback para mudar tab ativa\r\n */\r\nexport default function QuickActionsGrid({ onTabChange }) {\r\n const actions = [\r\n {\r\n label: 'Ver Architecture',\r\n icon: FileText,\r\n onClick: () => onTabChange?.('architecture'),\r\n color: 'emerald'\r\n },\r\n {\r\n label: 'Ver Logs',\r\n icon: GitBranch,\r\n onClick: () => onTabChange?.('logs'),\r\n color: 'blue'\r\n },\r\n {\r\n label: 'Tech Debt',\r\n icon: AlertTriangle,\r\n onClick: () => onTabChange?.('techdebt'),\r\n color: 'amber'\r\n },\r\n {\r\n label: 'Backlog',\r\n icon: Target,\r\n onClick: () => onTabChange?.('backlog'),\r\n color: 'purple'\r\n }\r\n ];\r\n\r\n const colorClasses = {\r\n emerald: 'bg-emerald-500/10 text-emerald-400 hover:bg-emerald-500/20 border-emerald-500/30',\r\n blue: 'bg-blue-500/10 text-blue-400 hover:bg-blue-500/20 border-blue-500/30',\r\n amber: 'bg-amber-500/10 text-amber-400 hover:bg-amber-500/20 border-amber-500/30',\r\n purple: 'bg-purple-500/10 text-purple-400 hover:bg-purple-500/20 border-purple-500/30'\r\n };\r\n\r\n return (\r\n <div className=\"bg-slate-800 border border-slate-700 rounded-lg p-6\">\r\n <h3 className=\"text-lg font-semibold text-slate-100 mb-4\">Ações Rápidas</h3>\r\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4\">\r\n {actions.map((action, index) => {\r\n const Icon = action.icon;\r\n return (\r\n <button\r\n key={index}\r\n onClick={action.onClick}\r\n className={`flex flex-col items-center justify-center p-4 rounded-lg border transition-colors ${colorClasses[action.color]} hover:scale-105`}\r\n >\r\n <Icon className=\"w-6 h-6 mb-2\" />\r\n <span className=\"text-sm font-medium\">{action.label}</span>\r\n </button>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import MetricCard from '../widgets/MetricCard';\r\nimport HealthScore from '../widgets/HealthScore';\r\nimport TechStackList from '../widgets/TechStackList';\r\nimport RecentActivityFeed from '../widgets/RecentActivityFeed';\r\nimport QuickActionsGrid from '../widgets/QuickActionsGrid';\r\n\r\n/**\r\n * Overview Tab\r\n * Tab principal com métricas gerais do projeto\r\n * \r\n * @param {Object} metrics - Métricas do projeto\r\n */\r\nexport default function OverviewTab({ metrics, onTabChange }) {\r\n if (!metrics) return null;\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Header */}\r\n <div>\r\n <h2 className=\"text-2xl font-bold text-slate-100 mb-2\">\r\n Project Health Overview\r\n </h2>\r\n <p className=\"text-slate-400\">\r\n Snapshot do estado atual do projeto\r\n </p>\r\n </div>\r\n\r\n {/* Health Score */}\r\n <HealthScore score={metrics.healthScore} />\r\n\r\n {/* Metrics Grid */}\r\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4\">\r\n <MetricCard\r\n title=\"Tech Debt\"\r\n value={metrics.techDebt.total}\r\n subtitle={`${metrics.techDebt.critical} críticos`}\r\n icon=\"⚠️\"\r\n trend={metrics.techDebt.critical > 0 ? 'danger' : 'success'}\r\n />\r\n \r\n <MetricCard\r\n title=\"Backlog Items\"\r\n value={metrics.backlog.total}\r\n subtitle={`${metrics.backlog.doing} em progresso`}\r\n icon=\"🎯\"\r\n trend=\"neutral\"\r\n />\r\n \r\n <MetricCard\r\n title=\"PLANs Ativos\"\r\n value={12}\r\n subtitle=\"3 em progresso\"\r\n icon=\"📋\"\r\n trend=\"success\"\r\n />\r\n \r\n <MetricCard\r\n title=\"Migrations\"\r\n value={14}\r\n subtitle=\"Todas aplicadas\"\r\n icon=\"🗄️\"\r\n trend=\"success\"\r\n />\r\n </div>\r\n\r\n {/* Two Columns */}\r\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\r\n {/* Tech Stack */}\r\n <TechStackList stack={metrics.techStack} />\r\n\r\n {/* Recent Activity */}\r\n <RecentActivityFeed activities={metrics.recentActivity} />\r\n </div>\r\n\r\n {/* Quick Actions */}\r\n <QuickActionsGrid onTabChange={onTabChange} />\r\n </div>\r\n );\r\n}\r\n","/**\r\n * Governance Data Fetcher\r\n * Carrega arquivos Markdown do filesystem (via fetch)\r\n * \r\n * @author Nexus Code\r\n * @date 2026-01-12\r\n */\r\n\r\nimport {\r\n parseTechDebtRegistry,\r\n parseBacklogRegistry,\r\n parseAllLogs,\r\n parsePlan,\r\n calculateHealthScore\r\n} from './governanceParser.js';\r\n\r\n/**\r\n * Fetch de arquivo Markdown\r\n * @param {string} path - Caminho relativo ao public/\r\n * @param {number|null} timestamp - Timestamp para cache-busting\r\n * @returns {Promise<string>} Conteúdo do arquivo\r\n */\r\nasync function fetchMarkdown(path, timestamp = null) {\r\n try {\r\n // Cache-busting: adiciona ?t=timestamp se fornecido\r\n const url = timestamp ? `${path}?t=${timestamp}` : path;\r\n \r\n const response = await fetch(url);\r\n if (!response.ok) throw new Error(`Failed to fetch ${path}`);\r\n return await response.text();\r\n } catch (error) {\r\n console.error(`Error fetching ${path}:`, error);\r\n return '';\r\n }\r\n}\r\n\r\n/**\r\n * Carregar Tech Debt Registry\r\n * @param {number|null} timestamp - Timestamp para cache-busting\r\n */\r\nexport async function loadTechDebtData(timestamp = null) {\r\n try {\r\n // Busca direto da fonte (/docs/) em vez de /public/docs/\r\n const basePath = timestamp ? '../docs' : '/docs';\r\n const content = await fetchMarkdown(`${basePath}/TECHNICAL_DEBT_REGISTRY.md`, timestamp);\r\n return parseTechDebtRegistry(content);\r\n } catch (error) {\r\n console.error('Error loading tech debt data:', error);\r\n return { debts: [], stats: { total: 0, pending: 0, critical: 0, high: 0, medium: 0, low: 0 } };\r\n }\r\n}\r\n\r\n/**\r\n * Carregar Backlog Registry\r\n * @param {number|null} timestamp - Timestamp para cache-busting\r\n */\r\nexport async function loadBacklogData(timestamp = null) {\r\n try {\r\n // Busca direto da fonte (/docs/) em vez de /public/docs/\r\n const basePath = timestamp ? '../docs' : '/docs';\r\n const content = await fetchMarkdown(`${basePath}/BACKLOG_REGISTRY.md`, timestamp);\r\n return parseBacklogRegistry(content);\r\n } catch (error) {\r\n console.error('Error loading backlog data:', error);\r\n return { items: [], stats: { total: 0, highPriority: 0, mediumPriority: 0, lowPriority: 0, backlog: 0, planned: 0, doing: 0, done: 0 } };\r\n }\r\n}\r\n\r\n/**\r\n * Carregar todos os logs\r\n * @param {number|null} timestamp - Timestamp para cache-busting\r\n */\r\nexport async function loadLogsData(timestamp = null) {\r\n try {\r\n // Busca direto da fonte (/.logs/) - já está na raiz pública via Vite\r\n const [architecture, decisions] = await Promise.all([\r\n fetchMarkdown('/.logs/architecture.log.md', timestamp),\r\n fetchMarkdown('/.logs/decisions.log.md', timestamp)\r\n ]);\r\n \r\n return parseAllLogs({ architecture, decisions });\r\n } catch (error) {\r\n console.error('Error loading logs data:', error);\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Carregar lista de PLANs (requer endpoint ou build-time generation)\r\n * Para Fase 1-3, vamos criar lista manual de PLANs conhecidos\r\n */\r\nexport async function loadPlansData() {\r\n // ⚠️ TECH-DEBT: TD-004\r\n // TODO: Implementar scan dinâmico de docs/plans/*.md\r\n // Trigger: Fase 4 (Dashboard completo)\r\n // Por ora, lista hardcoded dos PLANs principais\r\n \r\n const knownPlans = [\r\n 'PLAN_DEV_DASHBOARD_GOVERNANCE.md',\r\n 'PLAN_TECHNICAL_DEBT_MANAGEMENT.md',\r\n 'PLAN_BACKLOG_MANAGEMENT.md',\r\n 'PLAN_SAAS_INTEGRATION_ARCHITECTURE.md',\r\n 'PLAN_CRM.md',\r\n 'PLAN_CRM_MELHORIAS.md'\r\n ];\r\n \r\n try {\r\n const plans = await Promise.all(\r\n knownPlans.map(async filename => {\r\n const content = await fetchMarkdown(`/docs/plans/${filename}`);\r\n return content ? parsePlan(content, filename) : null;\r\n })\r\n );\r\n \r\n return plans.filter(Boolean);\r\n } catch (error) {\r\n console.error('Error loading plans data:', error);\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Calcular métricas do projeto (Overview)\r\n * @param {number|null} timestamp - Timestamp para cache-busting\r\n */\r\nexport async function calculateProjectMetrics(timestamp = null) {\r\n try {\r\n const [techDebt, backlog, logs] = await Promise.all([\r\n loadTechDebtData(timestamp),\r\n loadBacklogData(timestamp),\r\n loadLogsData(timestamp)\r\n ]);\r\n \r\n return {\r\n healthScore: calculateHealthScore(techDebt.stats, backlog.stats),\r\n techDebt: techDebt.stats,\r\n backlog: backlog.stats,\r\n recentActivity: logs.slice(0, 5), // Últimas 5 entradas\r\n techStack: {\r\n frontend: 'React 19',\r\n backend: 'Supabase',\r\n database: 'PostgreSQL 17',\r\n styling: 'Tailwind CSS 4'\r\n }\r\n };\r\n } catch (error) {\r\n console.error('[ERROR] Error calculating project metrics:', error);\r\n return {\r\n healthScore: 0,\r\n techDebt: { total: 0, pending: 0, critical: 0, high: 0, medium: 0, low: 0 },\r\n backlog: { total: 0, highPriority: 0, mediumPriority: 0, lowPriority: 0, backlog: 0, planned: 0, doing: 0, done: 0 },\r\n recentActivity: [],\r\n techStack: {\r\n frontend: 'React 19',\r\n backend: 'Supabase',\r\n database: 'PostgreSQL 17',\r\n styling: 'Tailwind CSS 4'\r\n }\r\n };\r\n }\r\n}\r\n","/**\r\n * Debt Stats\r\n * Estatísticas de débitos técnicos\r\n * \r\n * @param {Object} stats - Estatísticas\r\n */\r\nexport default function DebtStats({ stats }) {\r\n const statCards = [\r\n { label: 'Total', value: stats.total, color: 'slate', icon: '📊' },\r\n { label: 'Críticos', value: stats.critical, color: 'red', icon: '🔴' },\r\n { label: 'Altos', value: stats.high, color: 'orange', icon: '🟠' },\r\n { label: 'Médios', value: stats.medium, color: 'amber', icon: '🟡' },\r\n { label: 'Baixos', value: stats.low, color: 'emerald', icon: '🟢' }\r\n ];\r\n\r\n const colorClasses = {\r\n slate: 'bg-slate-700 border-slate-600',\r\n red: 'bg-red-500/10 border-red-500/30',\r\n orange: 'bg-orange-500/10 border-orange-500/30',\r\n amber: 'bg-amber-500/10 border-amber-500/30',\r\n emerald: 'bg-emerald-500/10 border-emerald-500/30'\r\n };\r\n\r\n return (\r\n <div className=\"grid grid-cols-2 md:grid-cols-5 gap-4\">\r\n {statCards.map((card, index) => (\r\n <div\r\n key={index}\r\n className={`border rounded-lg p-4 ${colorClasses[card.color]}`}\r\n >\r\n <div className=\"flex items-center justify-between mb-2\">\r\n <span className=\"text-2xl\">{card.icon}</span>\r\n <span className=\"text-2xl font-bold text-slate-200\">\r\n {card.value}\r\n </span>\r\n </div>\r\n <p className=\"text-sm text-slate-400\">{card.label}</p>\r\n </div>\r\n ))}\r\n </div>\r\n );\r\n}\r\n","/**\r\n * Debt Filters\r\n * Filtros para débitos técnicos\r\n * \r\n * @param {Object} filters - Estado dos filtros\r\n * @param {Function} onFilterChange - Callback para mudança de filtros\r\n */\r\nexport default function DebtFilters({ filters, onFilterChange }) {\r\n const handleSeverityChange = (e) => {\r\n onFilterChange({ ...filters, severity: e.target.value });\r\n };\r\n\r\n const handleStatusChange = (e) => {\r\n onFilterChange({ ...filters, status: e.target.value });\r\n };\r\n\r\n const handleSearchChange = (e) => {\r\n onFilterChange({ ...filters, search: e.target.value });\r\n };\r\n\r\n return (\r\n <div className=\"bg-slate-800 border border-slate-700 rounded-lg p-4\">\r\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\r\n {/* Severity Filter */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-slate-300 mb-2\">\r\n Severidade\r\n </label>\r\n <select\r\n value={filters.severity}\r\n onChange={handleSeverityChange}\r\n className=\"w-full bg-slate-700 border border-slate-600 text-slate-200 rounded-lg px-3 py-2 focus:ring-2 focus:ring-emerald-500 focus:border-transparent\"\r\n >\r\n <option value=\"all\">Todas</option>\r\n <option value=\"crítico\">🔴 Crítico</option>\r\n <option value=\"alto\">🟠 Alto</option>\r\n <option value=\"médio\">🟡 Médio</option>\r\n <option value=\"baixo\">🟢 Baixo</option>\r\n </select>\r\n </div>\r\n\r\n {/* Status Filter */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-slate-300 mb-2\">\r\n Status\r\n </label>\r\n <select\r\n value={filters.status}\r\n onChange={handleStatusChange}\r\n className=\"w-full bg-slate-700 border border-slate-600 text-slate-200 rounded-lg px-3 py-2 focus:ring-2 focus:ring-emerald-500 focus:border-transparent\"\r\n >\r\n <option value=\"all\">Todos</option>\r\n <option value=\"pendente\">⏳ Pendente</option>\r\n <option value=\"resolvido\">✅ Resolvido</option>\r\n </select>\r\n </div>\r\n\r\n {/* Search */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-slate-300 mb-2\">\r\n Buscar\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={filters.search}\r\n onChange={handleSearchChange}\r\n placeholder=\"ID, descrição, arquivo...\"\r\n className=\"w-full bg-slate-700 border border-slate-600 text-slate-200 rounded-lg px-3 py-2 focus:ring-2 focus:ring-emerald-500 focus:border-transparent placeholder-slate-500\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { getSeverityIcon, getSeverityColor } from '../../utils/governanceParser';\r\n\r\n/**\r\n * Severity Badge\r\n * Badge colorido para severidade de débito técnico\r\n * \r\n * @param {string} severity - Severidade do débito\r\n */\r\nexport default function SeverityBadge({ severity }) {\r\n const icon = getSeverityIcon(severity);\r\n const colorClass = getSeverityColor(severity);\r\n\r\n return (\r\n <span className={`inline-flex items-center gap-1 px-2 py-1 rounded text-xs font-medium border ${colorClass}`}>\r\n <span>{icon}</span>\r\n <span>{severity}</span>\r\n </span>\r\n );\r\n}\r\n","/**\r\n * Governance Utilities\r\n * Utilitários diversos para o dashboard\r\n * \r\n * @author Nexus Code\r\n * @date 2026-01-12\r\n */\r\n\r\n/**\r\n * Contar arquivos de um tipo (via contagem hardcoded ou fetch)\r\n */\r\nexport async function countProjectFiles() {\r\n // ⚠️ TECH-DEBT: TD-005\r\n // TODO: Implementar contagem dinâmica via API ou build-time\r\n // Trigger: Fase 5 (Polish)\r\n // Por ora, valores aproximados\r\n \r\n return {\r\n components: 25, // src/components/**/*.jsx\r\n pages: 12, // src/pages/**/*.jsx\r\n migrations: 14, // supabase/migrations/*.sql\r\n plans: 15 // docs/plans/*.md\r\n };\r\n}\r\n\r\n/**\r\n * Debounce para busca/filtros\r\n */\r\nexport function debounce(func, wait) {\r\n let timeout;\r\n return function executedFunction(...args) {\r\n const later = () => {\r\n clearTimeout(timeout);\r\n func(...args);\r\n };\r\n clearTimeout(timeout);\r\n timeout = setTimeout(later, wait);\r\n };\r\n}\r\n\r\n/**\r\n * Filtrar array por texto (busca em múltiplas propriedades)\r\n */\r\nexport function filterBySearchText(items, searchText, ...properties) {\r\n if (!searchText) return items;\r\n \r\n const search = searchText.toLowerCase();\r\n return items.filter(item =>\r\n properties.some(prop => {\r\n const value = item[prop];\r\n return value && String(value).toLowerCase().includes(search);\r\n })\r\n );\r\n}\r\n\r\n/**\r\n * Agrupar itens por propriedade\r\n */\r\nexport function groupBy(items, property) {\r\n return items.reduce((acc, item) => {\r\n const key = item[property] || 'Outros';\r\n if (!acc[key]) acc[key] = [];\r\n acc[key].push(item);\r\n return acc;\r\n }, {});\r\n}\r\n\r\n/**\r\n * Copiar texto para clipboard\r\n */\r\nexport async function copyToClipboard(text) {\r\n try {\r\n await navigator.clipboard.writeText(text);\r\n return true;\r\n } catch (error) {\r\n console.error('Failed to copy:', error);\r\n return false;\r\n }\r\n}\r\n","import SeverityBadge from './SeverityBadge';\r\nimport { Copy } from 'lucide-react';\r\nimport { copyToClipboard } from '../../utils/governanceUtils';\r\n\r\n/**\r\n * Debt Card\r\n * Card para exibir débito técnico individual\r\n * \r\n * @param {Object} debt - Objeto de débito\r\n */\r\nexport default function DebtCard({ debt }) {\r\n const handleCopyId = async () => {\r\n const success = await copyToClipboard(debt.id);\r\n if (success) {\r\n // Feedback visual opcional\r\n console.log(`${debt.id} copiado!`);\r\n }\r\n };\r\n\r\n const isResolved = debt.status.includes('✅') || debt.status.toLowerCase().includes('resolvido');\r\n\r\n return (\r\n <div className={`bg-slate-800 border rounded-lg p-5 ${isResolved ? 'border-emerald-500/30 opacity-60' : 'border-slate-700'}`}>\r\n <div className=\"flex items-start justify-between gap-4 mb-3\">\r\n {/* ID and Copy Button */}\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n onClick={handleCopyId}\r\n className=\"flex items-center gap-2 text-sm font-mono font-semibold text-emerald-400 hover:text-emerald-300 transition-colors\"\r\n title=\"Copiar ID\"\r\n >\r\n {debt.id}\r\n <Copy className=\"w-3 h-3\" />\r\n </button>\r\n </div>\r\n\r\n {/* Severity Badge */}\r\n <SeverityBadge severity={debt.severity} />\r\n </div>\r\n\r\n {/* Description */}\r\n <p className=\"text-slate-200 mb-4\">{debt.description}</p>\r\n\r\n {/* Meta Info Grid */}\r\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-3 text-sm\">\r\n {/* Trigger */}\r\n <div>\r\n <span className=\"text-slate-500\">Trigger:</span>\r\n <p className=\"text-slate-300 font-medium mt-1\">{debt.trigger}</p>\r\n </div>\r\n\r\n {/* Location */}\r\n <div>\r\n <span className=\"text-slate-500\">Localização:</span>\r\n <p className=\"text-slate-300 font-mono text-xs mt-1 truncate\" title={debt.location}>\r\n {debt.location}\r\n </p>\r\n </div>\r\n\r\n {/* Owner */}\r\n <div>\r\n <span className=\"text-slate-500\">Owner:</span>\r\n <p className=\"text-slate-300 mt-1\">{debt.owner}</p>\r\n </div>\r\n </div>\r\n\r\n {/* Status */}\r\n <div className=\"mt-3 pt-3 border-t border-slate-700\">\r\n <span className=\"text-xs text-slate-500\">Status: </span>\r\n <span className=\"text-xs text-slate-300\">{debt.status}</span>\r\n {debt.created && (\r\n <>\r\n <span className=\"text-xs text-slate-600 mx-2\">•</span>\r\n <span className=\"text-xs text-slate-500\">Criado em: </span>\r\n <span className=\"text-xs text-slate-400\">{debt.created}</span>\r\n </>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { useState, useEffect } from 'react';\r\nimport { loadTechDebtData } from '../../utils/governanceData';\r\nimport DebtStats from '../techdebt/DebtStats';\r\nimport DebtFilters from '../techdebt/DebtFilters';\r\nimport DebtCard from '../techdebt/DebtCard';\r\n\r\n/**\r\n * Tech Debt Tab\r\n * Visualização de débitos técnicos do TECHNICAL_DEBT_REGISTRY.md\r\n */\r\nexport default function TechDebtTab() {\r\n const [data, setData] = useState(null);\r\n const [filteredDebts, setFilteredDebts] = useState([]);\r\n const [filters, setFilters] = useState({\r\n severity: 'all',\r\n status: 'all',\r\n search: ''\r\n });\r\n const [loading, setLoading] = useState(true);\r\n\r\n useEffect(() => {\r\n async function load() {\r\n try {\r\n const result = await loadTechDebtData();\r\n setData(result);\r\n setFilteredDebts(result.debts);\r\n } catch (error) {\r\n console.error('Error loading tech debt:', error);\r\n } finally {\r\n setLoading(false);\r\n }\r\n }\r\n load();\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (!data) return;\r\n\r\n let filtered = data.debts;\r\n\r\n // Filter by severity\r\n if (filters.severity !== 'all') {\r\n filtered = filtered.filter(debt => \r\n debt.severity.toLowerCase().includes(filters.severity.toLowerCase())\r\n );\r\n }\r\n\r\n // Filter by status\r\n if (filters.status !== 'all') {\r\n filtered = filtered.filter(debt =>\r\n debt.status.toLowerCase().includes(filters.status.toLowerCase())\r\n );\r\n }\r\n\r\n // Filter by search\r\n if (filters.search) {\r\n const search = filters.search.toLowerCase();\r\n filtered = filtered.filter(debt =>\r\n debt.id.toLowerCase().includes(search) ||\r\n debt.description.toLowerCase().includes(search) ||\r\n debt.location.toLowerCase().includes(search) ||\r\n debt.owner.toLowerCase().includes(search)\r\n );\r\n }\r\n\r\n setFilteredDebts(filtered);\r\n }, [filters, data]);\r\n\r\n if (loading) {\r\n return (\r\n <div className=\"flex items-center justify-center py-12\">\r\n <div className=\"animate-spin rounded-full h-8 w-8 border-b-2 border-emerald-500\"></div>\r\n </div>\r\n );\r\n }\r\n\r\n if (!data) {\r\n return (\r\n <div className=\"text-center py-12\">\r\n <p className=\"text-slate-500\">Erro ao carregar dados</p>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Header */}\r\n <div>\r\n <h2 className=\"text-2xl font-bold text-slate-100 mb-2\">\r\n Technical Debt Registry\r\n </h2>\r\n <p className=\"text-slate-400\">\r\n Débitos técnicos rastreados e priorizados\r\n </p>\r\n </div>\r\n\r\n {/* Stats */}\r\n <DebtStats stats={data.stats} />\r\n\r\n {/* Filters */}\r\n <DebtFilters filters={filters} onFilterChange={setFilters} />\r\n\r\n {/* Debts List */}\r\n <div className=\"space-y-4\">\r\n {filteredDebts.map((debt) => (\r\n <DebtCard key={debt.id} debt={debt} />\r\n ))}\r\n </div>\r\n\r\n {/* Empty State */}\r\n {filteredDebts.length === 0 && (\r\n <div className=\"text-center py-12\">\r\n <p className=\"text-slate-500\">Nenhum débito técnico encontrado</p>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","/**\r\n * Backlog Stats\r\n * Estatísticas de itens de backlog\r\n * \r\n * @param {Object} stats - Estatísticas\r\n */\r\nexport default function BacklogStats({ stats }) {\r\n const statCards = [\r\n { label: 'Total', value: stats.total, color: 'slate', icon: '📊' },\r\n { label: 'Backlog', value: stats.backlog, color: 'slate', icon: '📋' },\r\n { label: 'Planned', value: stats.planned, color: 'blue', icon: '📅' },\r\n { label: 'Em Progresso', value: stats.doing, color: 'amber', icon: '🚧' },\r\n { label: 'Concluídos', value: stats.done, color: 'emerald', icon: '✅' }\r\n ];\r\n\r\n const colorClasses = {\r\n slate: 'bg-slate-700 border-slate-600',\r\n blue: 'bg-blue-500/10 border-blue-500/30',\r\n amber: 'bg-amber-500/10 border-amber-500/30',\r\n emerald: 'bg-emerald-500/10 border-emerald-500/30'\r\n };\r\n\r\n return (\r\n <div className=\"grid grid-cols-2 md:grid-cols-5 gap-4\">\r\n {statCards.map((card, index) => (\r\n <div\r\n key={index}\r\n className={`border rounded-lg p-4 ${colorClasses[card.color]}`}\r\n >\r\n <div className=\"flex items-center justify-between mb-2\">\r\n <span className=\"text-2xl\">{card.icon}</span>\r\n <span className=\"text-2xl font-bold text-slate-200\">\r\n {card.value}\r\n </span>\r\n </div>\r\n <p className=\"text-sm text-slate-400\">{card.label}</p>\r\n </div>\r\n ))}\r\n </div>\r\n );\r\n}\r\n","/**\r\n * Backlog Filters\r\n * Filtros para itens de backlog\r\n * \r\n * @param {Object} filters - Estado dos filtros\r\n * @param {Function} onFilterChange - Callback para mudança de filtros\r\n */\r\nexport default function BacklogFilters({ filters, onFilterChange }) {\r\n const handleStatusChange = (e) => {\r\n onFilterChange({ ...filters, status: e.target.value });\r\n };\r\n\r\n const handleCategoryChange = (e) => {\r\n onFilterChange({ ...filters, category: e.target.value });\r\n };\r\n\r\n const handleSearchChange = (e) => {\r\n onFilterChange({ ...filters, search: e.target.value });\r\n };\r\n\r\n return (\r\n <div className=\"bg-slate-800 border border-slate-700 rounded-lg p-4\">\r\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\r\n {/* Status Filter */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-slate-300 mb-2\">\r\n Status\r\n </label>\r\n <select\r\n value={filters.status}\r\n onChange={handleStatusChange}\r\n className=\"w-full bg-slate-700 border border-slate-600 text-slate-200 rounded-lg px-3 py-2 focus:ring-2 focus:ring-emerald-500 focus:border-transparent\"\r\n >\r\n <option value=\"all\">Todos</option>\r\n <option value=\"backlog\">📋 Backlog</option>\r\n <option value=\"planned\">📅 Planned</option>\r\n <option value=\"doing\">🚧 Doing</option>\r\n <option value=\"done\">✅ Done</option>\r\n </select>\r\n </div>\r\n\r\n {/* Category Filter */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-slate-300 mb-2\">\r\n Categoria\r\n </label>\r\n <select\r\n value={filters.category}\r\n onChange={handleCategoryChange}\r\n className=\"w-full bg-slate-700 border border-slate-600 text-slate-200 rounded-lg px-3 py-2 focus:ring-2 focus:ring-emerald-500 focus:border-transparent\"\r\n >\r\n <option value=\"all\">Todas</option>\r\n <option value=\"feature\">✨ Feature</option>\r\n <option value=\"improvement\">⚡ Improvement</option>\r\n <option value=\"research\">🔬 Research</option>\r\n <option value=\"integration\">🔗 Integration</option>\r\n <option value=\"ui/ux\">🎨 UI/UX</option>\r\n </select>\r\n </div>\r\n\r\n {/* Search */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-slate-300 mb-2\">\r\n Buscar\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={filters.search}\r\n onChange={handleSearchChange}\r\n placeholder=\"ID, título, owner...\"\r\n className=\"w-full bg-slate-700 border border-slate-600 text-slate-200 rounded-lg px-3 py-2 focus:ring-2 focus:ring-emerald-500 focus:border-transparent placeholder-slate-500\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { getCategoryIcon } from '../../utils/governanceParser';\r\n\r\n/**\r\n * Category Badge\r\n * Badge colorido para categoria de backlog\r\n * \r\n * @param {string} category - Categoria do item\r\n */\r\nexport default function CategoryBadge({ category }) {\r\n const icon = getCategoryIcon(category);\r\n\r\n const categoryColors = {\r\n '✨': 'bg-purple-500/20 text-purple-400 border-purple-500/30',\r\n '⚡': 'bg-blue-500/20 text-blue-400 border-blue-500/30',\r\n '🔬': 'bg-amber-500/20 text-amber-400 border-amber-500/30',\r\n '🔗': 'bg-emerald-500/20 text-emerald-400 border-emerald-500/30',\r\n '🎨': 'bg-pink-500/20 text-pink-400 border-pink-500/30'\r\n };\r\n\r\n const colorClass = categoryColors[icon] || 'bg-slate-700 text-slate-400 border-slate-600';\r\n\r\n return (\r\n <span className={`inline-flex items-center gap-1 px-2 py-1 rounded text-xs font-medium border ${colorClass}`}>\r\n <span>{icon}</span>\r\n <span>{category}</span>\r\n </span>\r\n );\r\n}\r\n","import CategoryBadge from './CategoryBadge';\r\nimport { getStatusColor } from '../../utils/governanceParser';\r\nimport { Copy } from 'lucide-react';\r\nimport { copyToClipboard } from '../../utils/governanceUtils';\r\n\r\n/**\r\n * Backlog Item\r\n * Card para item de backlog individual\r\n * \r\n * @param {Object} item - Objeto de item de backlog\r\n */\r\nexport default function BacklogItem({ item }) {\r\n const handleCopyId = async () => {\r\n const success = await copyToClipboard(item.id);\r\n if (success) {\r\n console.log(`${item.id} copiado!`);\r\n }\r\n };\r\n\r\n const statusColor = getStatusColor(item.status);\r\n const isDone = item.status.includes('✅') || item.status.toLowerCase().includes('done');\r\n\r\n return (\r\n <div className={`bg-slate-800 border rounded-lg p-5 ${isDone ? 'border-emerald-500/30 opacity-60' : 'border-slate-700'}`}>\r\n <div className=\"flex items-start justify-between gap-4 mb-3\">\r\n {/* ID and Copy Button */}\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n onClick={handleCopyId}\r\n className=\"flex items-center gap-2 text-sm font-mono font-semibold text-emerald-400 hover:text-emerald-300 transition-colors\"\r\n title=\"Copiar ID\"\r\n >\r\n {item.id}\r\n <Copy className=\"w-3 h-3\" />\r\n </button>\r\n </div>\r\n\r\n {/* Category Badge */}\r\n <CategoryBadge category={item.category} />\r\n </div>\r\n\r\n {/* Title */}\r\n <h3 className=\"text-lg font-medium text-slate-200 mb-4\">{item.title}</h3>\r\n\r\n {/* Meta Info Grid */}\r\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-3 text-sm\">\r\n {/* Status */}\r\n <div>\r\n <span className=\"text-slate-500\">Status:</span>\r\n <p className=\"mt-1\">\r\n <span className={`inline-flex items-center px-2 py-1 rounded text-xs font-medium ${statusColor}`}>\r\n {item.status}\r\n </span>\r\n </p>\r\n </div>\r\n\r\n {/* Owner */}\r\n <div>\r\n <span className=\"text-slate-500\">Owner:</span>\r\n <p className=\"text-slate-300 mt-1\">{item.owner}</p>\r\n </div>\r\n\r\n {/* Estimate */}\r\n <div>\r\n <span className=\"text-slate-500\">Estimativa:</span>\r\n <p className=\"text-slate-300 mt-1\">{item.estimate}</p>\r\n </div>\r\n </div>\r\n\r\n {/* Created Date */}\r\n {item.created && (\r\n <div className=\"mt-3 pt-3 border-t border-slate-700\">\r\n <span className=\"text-xs text-slate-500\">Criado em: </span>\r\n <span className=\"text-xs text-slate-400\">{item.created}</span>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { useState, useEffect } from 'react';\r\nimport { loadBacklogData } from '../../utils/governanceData';\r\nimport BacklogStats from '../backlog/BacklogStats';\r\nimport BacklogFilters from '../backlog/BacklogFilters';\r\nimport BacklogItem from '../backlog/BacklogItem';\r\n\r\n/**\r\n * Backlog Tab\r\n * Visualização do BACKLOG_REGISTRY.md\r\n */\r\nexport default function BacklogTab() {\r\n const [data, setData] = useState(null);\r\n const [filteredItems, setFilteredItems] = useState([]);\r\n const [filters, setFilters] = useState({\r\n status: 'all',\r\n category: 'all',\r\n search: ''\r\n });\r\n const [loading, setLoading] = useState(true);\r\n\r\n useEffect(() => {\r\n async function load() {\r\n try {\r\n const result = await loadBacklogData();\r\n setData(result);\r\n setFilteredItems(result.items);\r\n } catch (error) {\r\n console.error('Error loading backlog:', error);\r\n } finally {\r\n setLoading(false);\r\n }\r\n }\r\n load();\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (!data) return;\r\n\r\n let filtered = data.items;\r\n\r\n // Filter by status\r\n if (filters.status !== 'all') {\r\n filtered = filtered.filter(item =>\r\n item.status.toLowerCase().includes(filters.status.toLowerCase())\r\n );\r\n }\r\n\r\n // Filter by category\r\n if (filters.category !== 'all') {\r\n filtered = filtered.filter(item =>\r\n item.category.toLowerCase().includes(filters.category.toLowerCase())\r\n );\r\n }\r\n\r\n // Filter by search\r\n if (filters.search) {\r\n const search = filters.search.toLowerCase();\r\n filtered = filtered.filter(item =>\r\n item.id.toLowerCase().includes(search) ||\r\n item.title.toLowerCase().includes(search) ||\r\n item.owner.toLowerCase().includes(search)\r\n );\r\n }\r\n\r\n setFilteredItems(filtered);\r\n }, [filters, data]);\r\n\r\n if (loading) {\r\n return (\r\n <div className=\"flex items-center justify-center py-12\">\r\n <div className=\"animate-spin rounded-full h-8 w-8 border-b-2 border-emerald-500\"></div>\r\n </div>\r\n );\r\n }\r\n\r\n if (!data) {\r\n return (\r\n <div className=\"text-center py-12\">\r\n <p className=\"text-slate-500\">Erro ao carregar dados</p>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Header */}\r\n <div>\r\n <h2 className=\"text-2xl font-bold text-slate-100 mb-2\">\r\n Backlog Registry\r\n </h2>\r\n <p className=\"text-slate-400\">\r\n Features e melhorias planejadas\r\n </p>\r\n </div>\r\n\r\n {/* Stats */}\r\n <BacklogStats stats={data.stats} />\r\n\r\n {/* Filters */}\r\n <BacklogFilters filters={filters} onFilterChange={setFilters} />\r\n\r\n {/* Items List */}\r\n <div className=\"space-y-4\">\r\n {filteredItems.map((item) => (\r\n <BacklogItem key={item.id} item={item} />\r\n ))}\r\n </div>\r\n\r\n {/* Empty State */}\r\n {filteredItems.length === 0 && (\r\n <div className=\"text-center py-12\">\r\n <p className=\"text-slate-500\">Nenhum item de backlog encontrado</p>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { useState } from 'react';\r\n\r\n/**\r\n * MarkdownViewer - Componente simples para renderizar Markdown\r\n * Não usa biblioteca externa, apenas CSS e regex para formatação básica\r\n */\r\nexport default function MarkdownViewer({ content, className = '' }) {\r\n const [collapsed, setCollapsed] = useState({});\r\n\r\n if (!content) {\r\n return (\r\n <div className=\"text-slate-500 italic\">\r\n Nenhum conteúdo disponível\r\n </div>\r\n );\r\n }\r\n\r\n // Parse markdown em elementos React\r\n const parseMarkdown = (text) => {\r\n const lines = text.split('\\n');\r\n const elements = [];\r\n let currentList = [];\r\n let currentCodeBlock = null;\r\n let codeLines = [];\r\n let inBlockquote = false;\r\n let blockquoteLines = [];\r\n\r\n const flushList = () => {\r\n if (currentList.length > 0) {\r\n elements.push(\r\n <ul key={`list-${elements.length}`} className=\"list-disc list-inside space-y-1 ml-4 text-slate-300\">\r\n {currentList.map((item, i) => (\r\n <li key={i} className=\"leading-relaxed\">{item}</li>\r\n ))}\r\n </ul>\r\n );\r\n currentList = [];\r\n }\r\n };\r\n\r\n const flushCodeBlock = () => {\r\n if (currentCodeBlock !== null) {\r\n const code = codeLines.join('\\n');\r\n elements.push(\r\n <div key={`code-${elements.length}`} className=\"my-4\">\r\n <div className=\"bg-slate-950 border border-slate-700 rounded-lg overflow-hidden\">\r\n <div className=\"px-3 py-2 bg-slate-800 border-b border-slate-700 text-xs text-slate-400\">\r\n {currentCodeBlock || 'code'}\r\n </div>\r\n <pre className=\"p-4 overflow-x-auto text-sm\">\r\n <code className=\"text-emerald-400 font-mono\">{code}</code>\r\n </pre>\r\n </div>\r\n </div>\r\n );\r\n currentCodeBlock = null;\r\n codeLines = [];\r\n }\r\n };\r\n\r\n const flushBlockquote = () => {\r\n if (blockquoteLines.length > 0) {\r\n elements.push(\r\n <blockquote key={`quote-${elements.length}`} className=\"border-l-4 border-emerald-500 pl-4 py-2 my-3 bg-emerald-500/5 text-slate-300 italic\">\r\n {blockquoteLines.join(' ')}\r\n </blockquote>\r\n );\r\n blockquoteLines = [];\r\n inBlockquote = false;\r\n }\r\n };\r\n\r\n lines.forEach((line, idx) => {\r\n // Code blocks\r\n if (line.startsWith('```')) {\r\n flushList();\r\n flushBlockquote();\r\n if (currentCodeBlock === null) {\r\n currentCodeBlock = line.slice(3).trim();\r\n } else {\r\n flushCodeBlock();\r\n }\r\n return;\r\n }\r\n\r\n if (currentCodeBlock !== null) {\r\n codeLines.push(line);\r\n return;\r\n }\r\n\r\n // Blockquotes\r\n if (line.startsWith('>')) {\r\n flushList();\r\n inBlockquote = true;\r\n blockquoteLines.push(line.slice(1).trim());\r\n return;\r\n } else if (inBlockquote) {\r\n flushBlockquote();\r\n }\r\n\r\n // Headers\r\n if (line.startsWith('# ')) {\r\n flushList();\r\n const text = line.slice(2);\r\n const sectionId = `section-${elements.length}`;\r\n const isCollapsed = collapsed[sectionId];\r\n \r\n elements.push(\r\n <div key={`h1-${idx}`} className=\"mb-4\">\r\n <h1 \r\n className=\"text-2xl font-bold text-emerald-400 mb-2 cursor-pointer hover:text-emerald-300 transition-colors flex items-center gap-2\"\r\n onClick={() => setCollapsed(prev => ({ ...prev, [sectionId]: !prev[sectionId] }))}\r\n >\r\n <span className=\"text-slate-500\">{isCollapsed ? '▶' : '▼'}</span>\r\n {formatInlineMarkdown(text)}\r\n </h1>\r\n {!isCollapsed && <div className=\"border-b border-slate-700 mb-4\"></div>}\r\n </div>\r\n );\r\n return;\r\n }\r\n\r\n if (line.startsWith('## ')) {\r\n flushList();\r\n elements.push(\r\n <h2 key={`h2-${idx}`} className=\"text-xl font-semibold text-slate-100 mt-6 mb-3\">\r\n {formatInlineMarkdown(line.slice(3))}\r\n </h2>\r\n );\r\n return;\r\n }\r\n\r\n if (line.startsWith('### ')) {\r\n flushList();\r\n elements.push(\r\n <h3 key={`h3-${idx}`} className=\"text-lg font-medium text-slate-200 mt-4 mb-2\">\r\n {formatInlineMarkdown(line.slice(4))}\r\n </h3>\r\n );\r\n return;\r\n }\r\n\r\n if (line.startsWith('#### ')) {\r\n flushList();\r\n elements.push(\r\n <h4 key={`h4-${idx}`} className=\"text-base font-medium text-slate-300 mt-3 mb-2\">\r\n {formatInlineMarkdown(line.slice(5))}\r\n </h4>\r\n );\r\n return;\r\n }\r\n\r\n // Horizontal rule\r\n if (line.trim() === '---' || line.trim() === '***') {\r\n flushList();\r\n elements.push(\r\n <hr key={`hr-${idx}`} className=\"my-6 border-slate-700\" />\r\n );\r\n return;\r\n }\r\n\r\n // Lists\r\n if (line.match(/^\\s*[-*+]\\s+/)) {\r\n const text = line.replace(/^\\s*[-*+]\\s+/, '');\r\n currentList.push(formatInlineMarkdown(text));\r\n return;\r\n } else {\r\n flushList();\r\n }\r\n\r\n // Paragraphs\r\n if (line.trim()) {\r\n elements.push(\r\n <p key={`p-${idx}`} className=\"text-slate-300 leading-relaxed mb-3\">\r\n {formatInlineMarkdown(line)}\r\n </p>\r\n );\r\n } else if (elements.length > 0) {\r\n // Empty line adds spacing\r\n elements.push(<div key={`space-${idx}`} className=\"h-2\"></div>);\r\n }\r\n });\r\n\r\n flushList();\r\n flushCodeBlock();\r\n flushBlockquote();\r\n\r\n return elements;\r\n };\r\n\r\n // Format inline markdown (bold, italic, code, links)\r\n const formatInlineMarkdown = (text) => {\r\n const parts = [];\r\n let lastIndex = 0;\r\n let key = 0;\r\n\r\n // Bold **text**\r\n const boldRegex = /\\*\\*(.+?)\\*\\*/g;\r\n // Italic *text*\r\n const italicRegex = /\\*(.+?)\\*/g;\r\n // Inline code `code`\r\n const codeRegex = /`([^`]+)`/g;\r\n // Links [text](url)\r\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\r\n // Emojis (já estão no texto, apenas renderizar)\r\n\r\n // Processar em ordem\r\n const combined = [];\r\n \r\n let match;\r\n // Find all matches\r\n while ((match = boldRegex.exec(text)) !== null) {\r\n combined.push({ type: 'bold', index: match.index, length: match[0].length, content: match[1] });\r\n }\r\n while ((match = italicRegex.exec(text)) !== null) {\r\n // Skip if already part of bold\r\n if (!combined.some(c => c.index <= match.index && match.index < c.index + c.length)) {\r\n combined.push({ type: 'italic', index: match.index, length: match[0].length, content: match[1] });\r\n }\r\n }\r\n while ((match = codeRegex.exec(text)) !== null) {\r\n combined.push({ type: 'code', index: match.index, length: match[0].length, content: match[1] });\r\n }\r\n while ((match = linkRegex.exec(text)) !== null) {\r\n combined.push({ type: 'link', index: match.index, length: match[0].length, content: match[1], url: match[2] });\r\n }\r\n\r\n // Sort by index\r\n combined.sort((a, b) => a.index - b.index);\r\n\r\n combined.forEach(item => {\r\n // Add text before this match\r\n if (item.index > lastIndex) {\r\n parts.push(<span key={`text-${key++}`}>{text.slice(lastIndex, item.index)}</span>);\r\n }\r\n\r\n // Add formatted element\r\n switch (item.type) {\r\n case 'bold':\r\n parts.push(<strong key={`bold-${key++}`} className=\"font-bold text-slate-100\">{item.content}</strong>);\r\n break;\r\n case 'italic':\r\n parts.push(<em key={`italic-${key++}`} className=\"italic\">{item.content}</em>);\r\n break;\r\n case 'code':\r\n parts.push(<code key={`code-${key++}`} className=\"bg-slate-800 text-emerald-400 px-1.5 py-0.5 rounded text-sm font-mono\">{item.content}</code>);\r\n break;\r\n case 'link':\r\n parts.push(\r\n <a \r\n key={`link-${key++}`} \r\n href={item.url} \r\n target=\"_blank\" \r\n rel=\"noopener noreferrer\"\r\n className=\"text-emerald-400 hover:text-emerald-300 underline\"\r\n >\r\n {item.content}\r\n </a>\r\n );\r\n break;\r\n }\r\n\r\n lastIndex = item.index + item.length;\r\n });\r\n\r\n // Add remaining text\r\n if (lastIndex < text.length) {\r\n parts.push(<span key={`text-${key++}`}>{text.slice(lastIndex)}</span>);\r\n }\r\n\r\n return parts.length > 0 ? parts : text;\r\n };\r\n\r\n return (\r\n <div className={`prose prose-invert max-w-none ${className}`}>\r\n {parseMarkdown(content)}\r\n </div>\r\n );\r\n}\r\n","import { useState } from 'react';\r\nimport { ChevronDown, ChevronRight } from 'lucide-react';\r\nimport { formatTimestamp } from '../../utils/governanceParser';\r\nimport MarkdownViewer from '../dashboard/MarkdownViewer';\r\n\r\n/**\r\n * Log Entry\r\n * Card expandível para cada entrada de log com formatação Markdown\r\n *\r\n * @param {Object} log - Objeto de log entry\r\n */\r\nexport default function LogEntry({ log }) {\r\n const [isExpanded, setIsExpanded] = useState(false);\r\n\r\n const logTypeColors = {\r\n architecture: 'border-blue-500/30 bg-blue-500/5',\r\n decisions: 'border-amber-500/30 bg-amber-500/5'\r\n };\r\n\r\n const logTypeLabels = {\r\n architecture: 'Arquitetura',\r\n decisions: 'Decisão'\r\n };\r\n\r\n const borderColor = logTypeColors[log.logType] || 'border-slate-700 bg-slate-800';\r\n\r\n return (\r\n <div className={`border rounded-lg overflow-hidden ${borderColor}`}>\r\n {/* Header (sempre visível) */}\r\n <button\r\n onClick={() => setIsExpanded(!isExpanded)}\r\n className=\"w-full p-4 flex items-start gap-3 hover:bg-slate-700/30 transition-colors\"\r\n >\r\n <div className=\"flex-shrink-0 mt-1\">\r\n {isExpanded ? (\r\n <ChevronDown className=\"w-5 h-5 text-slate-400\" />\r\n ) : (\r\n <ChevronRight className=\"w-5 h-5 text-slate-400\" />\r\n )}\r\n </div>\r\n \r\n <div className=\"flex-shrink-0 text-2xl\">\r\n {log.icon}\r\n </div>\r\n \r\n <div className=\"flex-1 text-left\">\r\n <div className=\"flex items-center gap-2 mb-1\">\r\n <h3 className=\"text-sm font-medium text-slate-200\">\r\n {log.title}\r\n </h3>\r\n <span className=\"text-xs px-2 py-0.5 rounded-full bg-slate-700 text-slate-300\">\r\n {logTypeLabels[log.logType] || log.logType}\r\n </span>\r\n </div>\r\n <div className=\"flex items-center gap-3 text-xs text-slate-500\">\r\n <span>{formatTimestamp(log.timestamp)}</span>\r\n {log.author && <span>• {log.author}</span>}\r\n {log.module && <span>• {log.module}</span>}\r\n {log.type && <span>• {log.type}</span>}\r\n </div>\r\n </div>\r\n </button>\r\n\r\n {/* Content (expandível) */}\r\n {isExpanded && (\r\n <div className=\"px-4 pb-4 pt-2 border-t border-slate-700 max-h-[600px] overflow-y-auto custom-scrollbar\">\r\n <MarkdownViewer content={log.content.trim()} />\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import LogEntry from './LogEntry';\r\n\r\n/**\r\n * Log Timeline\r\n * Timeline visual dos logs\r\n * \r\n * @param {Array} logs - Array de log entries\r\n */\r\nexport default function LogTimeline({ logs }) {\r\n if (!logs || logs.length === 0) {\r\n return null;\r\n }\r\n\r\n return (\r\n <div className=\"space-y-4\">\r\n {logs.map((log, index) => (\r\n <LogEntry key={`${log.timestamp}-${index}`} log={log} />\r\n ))}\r\n </div>\r\n );\r\n}\r\n","/**\r\n * Log Filters\r\n * Filtros para logs (tipo e busca)\r\n * \r\n * @param {Object} filters - Estado dos filtros\r\n * @param {Function} onFilterChange - Callback para mudança de filtros\r\n * @param {number} totalLogs - Total de logs carregados\r\n */\r\nexport default function LogFilters({ filters, onFilterChange, totalLogs }) {\r\n const handleTypeChange = (e) => {\r\n onFilterChange({ ...filters, type: e.target.value });\r\n };\r\n\r\n const handleSearchChange = (e) => {\r\n onFilterChange({ ...filters, search: e.target.value });\r\n };\r\n\r\n return (\r\n <div className=\"bg-slate-800 border border-slate-700 rounded-lg p-4\">\r\n <div className=\"flex flex-col md:flex-row gap-4\">\r\n {/* Type Filter */}\r\n <div className=\"flex-1\">\r\n <label className=\"block text-sm font-medium text-slate-300 mb-2\">\r\n Tipo de Log\r\n </label>\r\n <select\r\n value={filters.type}\r\n onChange={handleTypeChange}\r\n className=\"w-full bg-slate-700 border border-slate-600 text-slate-200 rounded-lg px-3 py-2 focus:ring-2 focus:ring-emerald-500 focus:border-transparent\"\r\n >\r\n <option value=\"all\">Todos</option>\r\n <option value=\"architecture\">🏗️ Architecture</option>\r\n <option value=\"decisions\">📝 Decisions</option>\r\n </select>\r\n </div>\r\n\r\n {/* Search */}\r\n <div className=\"flex-1\">\r\n <label className=\"block text-sm font-medium text-slate-300 mb-2\">\r\n Buscar\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={filters.search}\r\n onChange={handleSearchChange}\r\n placeholder=\"Digite para buscar...\"\r\n className=\"w-full bg-slate-700 border border-slate-600 text-slate-200 rounded-lg px-3 py-2 focus:ring-2 focus:ring-emerald-500 focus:border-transparent placeholder-slate-500\"\r\n />\r\n </div>\r\n\r\n {/* Stats */}\r\n <div className=\"flex items-end\">\r\n <div className=\"px-4 py-2 bg-slate-700 border border-slate-600 rounded-lg\">\r\n <span className=\"text-sm text-slate-400\">Total:</span>\r\n <span className=\"ml-2 text-lg font-bold text-emerald-400\">{totalLogs}</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { useState, useEffect } from 'react';\r\nimport { loadLogsData } from '../../utils/governanceData';\r\nimport LogTimeline from '../logs/LogTimeline';\r\nimport LogFilters from '../logs/LogFilters';\r\n\r\n/**\r\n * Logs Tab\r\n * Exibe timeline de logs (architecture.log.md e decisions.log.md)\r\n */\r\nexport default function LogsTab() {\r\n const [logs, setLogs] = useState([]);\r\n const [filteredLogs, setFilteredLogs] = useState([]);\r\n const [filters, setFilters] = useState({\r\n type: 'all',\r\n search: ''\r\n });\r\n const [loading, setLoading] = useState(true);\r\n\r\n useEffect(() => {\r\n async function load() {\r\n try {\r\n const data = await loadLogsData();\r\n // Limitar a 50 entradas para performance\r\n const limited = data.slice(0, 50);\r\n setLogs(limited);\r\n setFilteredLogs(limited);\r\n } catch (error) {\r\n console.error('Error loading logs:', error);\r\n } finally {\r\n setLoading(false);\r\n }\r\n }\r\n load();\r\n }, []);\r\n\r\n useEffect(() => {\r\n let filtered = logs;\r\n\r\n // Filter by type\r\n if (filters.type !== 'all') {\r\n filtered = filtered.filter(log => log.logType === filters.type);\r\n }\r\n\r\n // Filter by search\r\n if (filters.search) {\r\n const search = filters.search.toLowerCase();\r\n filtered = filtered.filter(log =>\r\n log.title.toLowerCase().includes(search) ||\r\n log.content.toLowerCase().includes(search)\r\n );\r\n }\r\n\r\n setFilteredLogs(filtered);\r\n }, [filters, logs]);\r\n\r\n if (loading) {\r\n return (\r\n <div className=\"flex items-center justify-center py-12\">\r\n <div className=\"animate-spin rounded-full h-8 w-8 border-b-2 border-emerald-500\"></div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Header */}\r\n <div>\r\n <h2 className=\"text-2xl font-bold text-slate-100 mb-2\">\r\n Logs Timeline\r\n </h2>\r\n <p className=\"text-slate-400\">\r\n Histórico de mudanças arquiteturais e decisões técnicas\r\n </p>\r\n </div>\r\n\r\n {/* Filters */}\r\n <LogFilters filters={filters} onFilterChange={setFilters} totalLogs={logs.length} />\r\n\r\n {/* Timeline */}\r\n <LogTimeline logs={filteredLogs} />\r\n\r\n {/* Empty State */}\r\n {filteredLogs.length === 0 && (\r\n <div className=\"text-center py-12\">\r\n <p className=\"text-slate-500\">Nenhum log encontrado</p>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { useState, useEffect } from 'react';\r\nimport MarkdownViewer from './MarkdownViewer';\r\n\r\n/**\r\n * Architecture Tab\r\n * Visualização do ARCHITECTURE.md com formatação\r\n */\r\nexport default function ArchitectureTab() {\r\n const [content, setContent] = useState('');\r\n const [loading, setLoading] = useState(true);\r\n const [activeTab, setActiveTab] = useState('architecture');\r\n\r\n useEffect(() => {\r\n async function loadContent() {\r\n try {\r\n const url = activeTab === 'architecture'\r\n ? '/docs/ARCHITECTURE.md'\r\n : '/docs/DATABASE_SCHEMA.md';\r\n \r\n const response = await fetch(url);\r\n if (!response.ok) throw new Error(`Failed to fetch ${url}`);\r\n const text = await response.text();\r\n setContent(text);\r\n } catch (error) {\r\n console.error('Error loading architecture doc:', error);\r\n setContent('## ❌ Erro ao Carregar\\n\\nNão foi possível carregar o documento. Verifique se os arquivos estão em `public/docs/`.');\r\n } finally {\r\n setLoading(false);\r\n }\r\n }\r\n \r\n setLoading(true);\r\n loadContent();\r\n }, [activeTab]);\r\n\r\n if (loading) {\r\n return (\r\n <div className=\"flex items-center justify-center py-12\">\r\n <div className=\"animate-spin rounded-full h-8 w-8 border-b-2 border-emerald-500\"></div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Header */}\r\n <div>\r\n <h2 className=\"text-2xl font-bold text-slate-100 mb-2\">\r\n Architecture Overview\r\n </h2>\r\n <p className=\"text-slate-400\">\r\n Documentação da arquitetura do sistema\r\n </p>\r\n </div>\r\n\r\n {/* Tabs */}\r\n <div className=\"flex gap-2 border-b border-slate-700\">\r\n <button\r\n onClick={() => setActiveTab('architecture')}\r\n className={`px-4 py-2 font-medium transition-colors ${\r\n activeTab === 'architecture'\r\n ? 'text-emerald-400 border-b-2 border-emerald-400'\r\n : 'text-slate-400 hover:text-slate-300'\r\n }`}\r\n >\r\n 🏗️ Architecture\r\n </button>\r\n <button\r\n onClick={() => setActiveTab('database')}\r\n className={`px-4 py-2 font-medium transition-colors ${\r\n activeTab === 'database'\r\n ? 'text-emerald-400 border-b-2 border-emerald-400'\r\n : 'text-slate-400 hover:text-slate-300'\r\n }`}\r\n >\r\n 🗄️ Database Schema\r\n </button>\r\n </div>\r\n\r\n {/* Content */}\r\n <div className=\"bg-slate-800 border border-slate-700 rounded-lg p-6 max-h-[calc(100vh-300px)] overflow-y-auto custom-scrollbar\">\r\n <MarkdownViewer content={content} />\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import React, { createContext, useContext } from 'react';\r\n\r\n/**\r\n * Context para configuração centralizada do Governance.\r\n * \r\n * Permite passar dependências via Provider ao invés de prop drilling.\r\n * \r\n * @type {React.Context<GovernanceContextValue>}\r\n */\r\nconst GovernanceContext = createContext(null);\r\n\r\n/**\r\n * Provider para configuração do Governance.\r\n * \r\n * @param {Object} props\r\n * @param {React.ReactNode} props.children - Componentes filhos\r\n * @param {Object} [props.utils] - Utilitários (copyToClipboard, maskCredential)\r\n * @param {Object} [props.client] - Cliente de banco de dados\r\n * @param {Object} [props.config] - Configurações (supabase, etc)\r\n * @param {Function} [props.healthCheck] - Função de health check\r\n * @param {React.Component} [props.ChatInterface] - Componente de chat\r\n * @param {Object} [props.chatConfig] - Configuração do chat\r\n * \r\n * @example\r\n * // Uso básico\r\n * import { GovernanceProvider } from '@bricks2k/governance';\r\n * import { copyToClipboard, maskCredential } from './lib/credentialUtils';\r\n * import { supabase } from './lib/supabase';\r\n * \r\n * <GovernanceProvider\r\n * utils={{ copyToClipboard, maskCredential }}\r\n * client={supabase}\r\n * config={{ supabase: SUPABASE_CONFIG }}\r\n * healthCheck={healthCheckWithCache}\r\n * >\r\n * <GovernanceDashboard />\r\n * </GovernanceProvider>\r\n * \r\n * @example\r\n * // Uso com Chat\r\n * <GovernanceProvider\r\n * utils={{ copyToClipboard, maskCredential }}\r\n * ChatInterface={ChatInterface}\r\n * chatConfig={{ endpoint: '...', context: 'dev' }}\r\n * >\r\n * <DevAssistantTab />\r\n * </GovernanceProvider>\r\n */\r\nexport function GovernanceProvider({ \r\n children, \r\n utils,\r\n client,\r\n config,\r\n healthCheck,\r\n ChatInterface,\r\n chatConfig\r\n}) {\r\n const value = {\r\n utils: utils || {\r\n // Fallback: implementações nativas\r\n copyToClipboard: async (text) => {\r\n await navigator.clipboard.writeText(text);\r\n },\r\n maskCredential: (value) => '•'.repeat(value.length)\r\n },\r\n client,\r\n config,\r\n healthCheck,\r\n ChatInterface,\r\n chatConfig\r\n };\r\n\r\n return (\r\n <GovernanceContext.Provider value={value}>\r\n {children}\r\n </GovernanceContext.Provider>\r\n );\r\n}\r\n\r\n/**\r\n * Hook para acessar o contexto do Governance.\r\n * \r\n * **IMPORTANTE:** Este hook retorna `null` se usado fora do Provider.\r\n * Componentes devem implementar fallback para props.\r\n * \r\n * @returns {GovernanceContextValue | null} Valor do contexto ou null\r\n * \r\n * @example\r\n * // Em um componente\r\n * function MyComponent({ onCopy }) {\r\n * const context = useGovernance();\r\n * \r\n * // Prioridade: props > context > default\r\n * const copyFn = onCopy || context?.utils?.copyToClipboard || defaultCopy;\r\n * \r\n * return <button onClick={() => copyFn('text')}>Copy</button>;\r\n * }\r\n */\r\nexport function useGovernance() {\r\n return useContext(GovernanceContext);\r\n}\r\n\r\n/**\r\n * Fallbacks nativos para uso standalone.\r\n * Exportados para facilitar implementação de defaults em componentes.\r\n */\r\nexport const defaultUtils = {\r\n copyToClipboard: async (text) => {\r\n try {\r\n await navigator.clipboard.writeText(text);\r\n } catch (error) {\r\n console.error('Failed to copy:', error);\r\n throw error;\r\n }\r\n },\r\n \r\n maskCredential: (value) => {\r\n if (!value) return '';\r\n return '•'.repeat(value.length);\r\n }\r\n};\r\n","import { ExternalLink, Copy, Check } from 'lucide-react';\r\nimport { useState } from 'react';\r\nimport { useGovernance } from '../../contexts/GovernanceContext';\r\n\r\n/**\r\n * Card reutilizável para exibir serviços do Supabase.\r\n *\r\n * @param {Object} props\r\n * @param {string} props.name - Nome do serviço\r\n * @param {string} props.url - URL do serviço\r\n * @param {string} [props.status='checking'] - Status: 'online' | 'offline' | 'checking'\r\n * @param {string} [props.icon='🔗'] - Emoji icon\r\n * @param {string} [props.description] - Descrição do serviço (opcional)\r\n * @param {Function} [props.onCopy] - Callback para copiar URL\r\n *\r\n * @example\r\n * <ServiceCard\r\n * name=\"Supabase Studio\"\r\n * url=\"http://localhost:54323\"\r\n * status=\"online\"\r\n * icon=\"🎨\"\r\n * description=\"Database manager\"\r\n * onCopy={copyToClipboard}\r\n * />\r\n */\r\nexport default function ServiceCard({\r\n name,\r\n url,\r\n status = 'checking',\r\n icon = '🔗',\r\n description,\r\n onCopy\r\n}) {\r\n const context = useGovernance();\r\n const [copied, setCopied] = useState(false);\r\n\r\n // 🆕 Fallback: props > context > default\r\n const copyFn = onCopy || context?.utils?.copyToClipboard;\r\n\r\n const handleCopy = async () => {\r\n try {\r\n if (copyFn) {\r\n await copyFn(url);\r\n } else {\r\n // Fallback: API nativa do navegador\r\n await navigator.clipboard.writeText(url);\r\n }\r\n \r\n setCopied(true);\r\n setTimeout(() => setCopied(false), 2000);\r\n } catch (error) {\r\n console.error('Erro ao copiar:', error);\r\n alert('Erro ao copiar URL');\r\n }\r\n };\r\n\r\n const handleOpen = () => {\r\n window.open(url, '_blank', 'noopener,noreferrer');\r\n };\r\n\r\n const getStatusConfig = () => {\r\n switch (status) {\r\n case 'online':\r\n return {\r\n badge: '🟢 Online',\r\n bgColor: 'bg-green-500/10',\r\n borderColor: 'border-green-500/30',\r\n textColor: 'text-green-400'\r\n };\r\n case 'offline':\r\n return {\r\n badge: '🔴 Offline',\r\n bgColor: 'bg-red-500/10',\r\n borderColor: 'border-red-500/30',\r\n textColor: 'text-red-400'\r\n };\r\n case 'checking':\r\n default:\r\n return {\r\n badge: '🟡 Verificando...',\r\n bgColor: 'bg-yellow-500/10',\r\n borderColor: 'border-yellow-500/30',\r\n textColor: 'text-yellow-400'\r\n };\r\n }\r\n };\r\n\r\n const statusConfig = getStatusConfig();\r\n const isDisabled = status === 'offline' || status === 'checking';\r\n\r\n return (\r\n <div className={`rounded-lg border ${statusConfig.borderColor} ${statusConfig.bgColor} p-4 transition-all hover:shadow-lg`}>\r\n <div className=\"flex items-start justify-between mb-3\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-2xl\">{icon}</span>\r\n <div>\r\n <h3 className=\"font-semibold text-slate-100\">{name}</h3>\r\n {description && (\r\n <p className=\"text-xs text-slate-400 mt-0.5\">{description}</p>\r\n )}\r\n </div>\r\n </div>\r\n <span className={`text-xs font-medium px-2 py-1 rounded ${statusConfig.textColor}`}>\r\n {statusConfig.badge}\r\n </span>\r\n </div>\r\n\r\n <div className=\"mb-3\">\r\n <code className=\"text-xs text-slate-300 bg-slate-800 px-2 py-1 rounded block truncate\">\r\n {url}\r\n </code>\r\n </div>\r\n\r\n <div className=\"flex gap-2\">\r\n <button\r\n onClick={handleOpen}\r\n disabled={isDisabled}\r\n className={`flex-1 flex items-center justify-center gap-2 px-3 py-2 rounded-lg text-sm font-medium transition-colors ${\r\n isDisabled\r\n ? 'bg-slate-700 text-slate-500 cursor-not-allowed'\r\n : 'bg-blue-600 hover:bg-blue-700 text-white'\r\n }`}\r\n title={isDisabled ? 'Serviço offline' : 'Abrir em nova aba'}\r\n >\r\n <ExternalLink className=\"w-4 h-4\" />\r\n Abrir\r\n </button>\r\n\r\n <button\r\n onClick={handleCopy}\r\n className=\"flex items-center justify-center gap-2 px-3 py-2 rounded-lg text-sm font-medium bg-slate-700 hover:bg-slate-600 text-slate-200 transition-colors\"\r\n title=\"Copiar URL\"\r\n >\r\n {copied ? (\r\n <>\r\n <Check className=\"w-4 h-4 text-green-400\" />\r\n <span className=\"text-green-400\">Copiado!</span>\r\n </>\r\n ) : (\r\n <>\r\n <Copy className=\"w-4 h-4\" />\r\n Copiar\r\n </>\r\n )}\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import ServiceCard from './ServiceCard';\r\n\r\n/**\r\n * Seção de Development Tools (Studio, Mailpit, MCP).\r\n *\r\n * @param {Object} props\r\n * @param {Array} props.tools - Lista de ferramentas de desenvolvimento\r\n * @param {string} props.tools[].id - ID único da ferramenta\r\n * @param {string} props.tools[].name - Nome da ferramenta\r\n * @param {string} props.tools[].url - URL da ferramenta\r\n * @param {string} props.tools[].icon - Emoji/ícone da ferramenta\r\n * @param {string} props.tools[].description - Descrição da ferramenta\r\n * @param {Object} [props.healthStatus={}] - Status dos serviços { studio: 'online', mailpit: 'offline', ... }\r\n *\r\n * @example\r\n * const tools = [\r\n * {\r\n * id: 'studio',\r\n * name: 'Supabase Studio',\r\n * url: 'http://localhost:54323',\r\n * icon: '🎨',\r\n * description: 'Database manager'\r\n * }\r\n * ];\r\n *\r\n * <DevToolsSection tools={tools} healthStatus={{ studio: 'online' }} />\r\n */\r\nexport default function DevToolsSection({ tools, healthStatus = {} }) {\r\n return (\r\n <div className=\"space-y-4\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-2xl\">🛠️</span>\r\n <h2 className=\"text-xl font-semibold text-slate-100\">Development Tools</h2>\r\n </div>\r\n \r\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">\r\n {tools.map((tool) => (\r\n <ServiceCard\r\n key={tool.id}\r\n name={tool.name}\r\n url={tool.url}\r\n icon={tool.icon}\r\n description={tool.description}\r\n status={healthStatus[tool.id] || 'checking'}\r\n />\r\n ))}\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { Eye, EyeOff, Copy, Check } from 'lucide-react';\r\nimport { useState } from 'react';\r\nimport { useGovernance } from '../../contexts/GovernanceContext';\r\n\r\n/**\r\n * Campo de credencial com mascaramento e toggle de visibilidade.\r\n *\r\n * @param {Object} props\r\n * @param {string} props.label - Label do campo\r\n * @param {string} props.value - Valor da credencial\r\n * @param {Function} [props.onCopy] - Callback para copiar (default: navigator.clipboard)\r\n * @param {Function} [props.maskFunction] - Função para mascarar (default: bullets)\r\n * @param {string} [props.warning] - Mensagem de aviso (opcional)\r\n * @param {string} [props.placeholder='Não configurada'] - Placeholder se valor ausente\r\n *\r\n * @example\r\n * // Com implementação customizada\r\n * <CredentialField\r\n * label=\"API Key\"\r\n * value=\"sk_test_123\"\r\n * onCopy={copyToClipboard}\r\n * maskFunction={maskCredential}\r\n * />\r\n *\r\n * @example\r\n * // Com defaults (funciona standalone)\r\n * <CredentialField\r\n * label=\"API Key\"\r\n * value=\"sk_test_123\"\r\n * />\r\n */\r\nexport default function CredentialField({\r\n label,\r\n value,\r\n onCopy,\r\n maskFunction,\r\n warning,\r\n placeholder = 'Não configurada'\r\n}) {\r\n // 🆕 Usar context\r\n const context = useGovernance();\r\n \r\n // 🆕 Fallback: props > context > defaults\r\n const copyFn = onCopy || context?.utils?.copyToClipboard;\r\n const maskFn = maskFunction || context?.utils?.maskCredential;\r\n \r\n const [isVisible, setIsVisible] = useState(false);\r\n const [copied, setCopied] = useState(false);\r\n\r\n const handleCopy = async () => {\r\n if (!value) return;\r\n \r\n try {\r\n if (copyFn) {\r\n // Usa função customizada fornecida (via props ou context)\r\n await copyFn(value);\r\n } else {\r\n // Fallback: API nativa do navegador\r\n await navigator.clipboard.writeText(value);\r\n }\r\n \r\n setCopied(true);\r\n setTimeout(() => setCopied(false), 2000);\r\n } catch (error) {\r\n console.error('Erro ao copiar:', error);\r\n alert('Erro ao copiar para área de transferência');\r\n }\r\n };\r\n\r\n const toggleVisibility = () => {\r\n setIsVisible(!isVisible);\r\n };\r\n\r\n // Aplica mascaramento customizado ou fallback com bullets\r\n const getMaskedValue = (val) => {\r\n if (maskFn) {\r\n return maskFn(val);\r\n }\r\n // Fallback: mascaramento simples com bullets\r\n return '•'.repeat(val.length);\r\n };\r\n\r\n const displayValue = value\r\n ? (isVisible ? value : getMaskedValue(value))\r\n : placeholder;\r\n\r\n const hasValue = Boolean(value);\r\n\r\n return (\r\n <div className=\"space-y-2\">\r\n <label className=\"text-sm font-medium text-slate-300 flex items-center gap-2\">\r\n {label}\r\n </label>\r\n \r\n <div className={`flex items-center gap-2 rounded-lg border p-3 transition-colors ${\r\n hasValue \r\n ? 'bg-slate-800 border-slate-700' \r\n : 'bg-slate-900 border-slate-800'\r\n }`}>\r\n <code className={`flex-1 text-sm font-mono truncate ${\r\n hasValue ? 'text-slate-200' : 'text-slate-500 italic'\r\n }`}>\r\n {displayValue}\r\n </code>\r\n \r\n {hasValue && (\r\n <>\r\n <button\r\n onClick={toggleVisibility}\r\n className=\"p-2 text-slate-400 hover:text-slate-200 hover:bg-slate-700 rounded transition-colors\"\r\n title={isVisible ? 'Ocultar' : 'Mostrar'}\r\n type=\"button\"\r\n >\r\n {isVisible ? (\r\n <EyeOff className=\"w-4 h-4\" />\r\n ) : (\r\n <Eye className=\"w-4 h-4\" />\r\n )}\r\n </button>\r\n \r\n <button\r\n onClick={handleCopy}\r\n className=\"p-2 text-slate-400 hover:text-slate-200 hover:bg-slate-700 rounded transition-colors\"\r\n title={copied ? 'Copiado!' : 'Copiar'}\r\n type=\"button\"\r\n >\r\n {copied ? (\r\n <Check className=\"w-4 h-4 text-green-400\" />\r\n ) : (\r\n <Copy className=\"w-4 h-4\" />\r\n )}\r\n </button>\r\n </>\r\n )}\r\n </div>\r\n \r\n {warning && hasValue && (\r\n <p className=\"text-xs text-amber-400 flex items-center gap-1.5 bg-amber-500/10 border border-amber-500/30 rounded px-2 py-1.5\">\r\n <span>⚠️</span>\r\n <span>{warning}</span>\r\n </p>\r\n )}\r\n\r\n {!hasValue && (\r\n <p className=\"text-xs text-slate-500 flex items-center gap-1.5\">\r\n <span>ℹ️</span>\r\n <span>Configure esta variável no arquivo <code className=\"bg-slate-800 px-1 rounded\">.env</code></span>\r\n </p>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import CredentialField from './CredentialField';\r\n\r\n/**\r\n * Seção de Authentication Keys (Anon Key e Service Role Key)\r\n */\r\nexport default function AuthKeysSection() {\r\n const anonKey = import.meta.env.VITE_SUPABASE_ANON_KEY;\r\n const serviceRoleKey = import.meta.env.VITE_SUPABASE_SERVICE_ROLE_KEY;\r\n\r\n return (\r\n <div className=\"space-y-4\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-2xl\">🔐</span>\r\n <h2 className=\"text-xl font-semibold text-slate-100\">Authentication Keys</h2>\r\n </div>\r\n\r\n {/* Banner de Segurança */}\r\n <div className=\"bg-red-500/10 border border-red-500/30 rounded-lg p-4\">\r\n <p className=\"text-red-300 text-sm flex items-center gap-2\">\r\n <span className=\"text-lg\">⚠️</span>\r\n <strong>ATENÇÃO:</strong> Nunca commitar a Service Role Key no repositório. \r\n Esta chave tem acesso total ao banco de dados.\r\n </p>\r\n </div>\r\n\r\n <div className=\"bg-slate-800 p-6 rounded-lg border border-slate-700 space-y-4\">\r\n {/* Anon Key */}\r\n <CredentialField\r\n label=\"Anon Key (Public)\"\r\n value={anonKey}\r\n placeholder=\"Configure VITE_SUPABASE_ANON_KEY no .env\"\r\n />\r\n\r\n {/* Service Role Key */}\r\n <CredentialField\r\n label=\"Service Role Key (Private)\"\r\n value={serviceRoleKey}\r\n warning=\"Esta chave tem acesso administrativo total. Use apenas em development.\"\r\n placeholder=\"Configure VITE_SUPABASE_SERVICE_ROLE_KEY no .env\"\r\n />\r\n\r\n {/* Info sobre as Keys */}\r\n <div className=\"pt-4 border-t border-slate-700\">\r\n <p className=\"text-xs text-slate-400 mb-2\">\r\n <strong className=\"text-slate-300\">Como obter as keys:</strong>\r\n </p>\r\n <ol className=\"text-xs text-slate-400 space-y-1 list-decimal list-inside\">\r\n <li>Execute: <code className=\"bg-slate-900 px-1.5 py-0.5 rounded text-slate-300\">npx supabase start</code></li>\r\n <li>Execute: <code className=\"bg-slate-900 px-1.5 py-0.5 rounded text-slate-300\">npx supabase status</code></li>\r\n <li>Copie as keys exibidas para o arquivo <code className=\"bg-slate-900 px-1.5 py-0.5 rounded text-slate-300\">.env</code></li>\r\n </ol>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { useState, useEffect } from 'react';\r\nimport { RefreshCw } from 'lucide-react';\r\nimport { useGovernance } from '../../contexts/GovernanceContext';\r\n\r\n/**\r\n * Seção de Health Status com verificação de serviços.\r\n *\r\n * @param {Object} props\r\n * @param {Function} [props.healthCheck] - Função para verificar health dos serviços\r\n * @returns Promise<Object> com status de cada serviço\r\n *\r\n * @example\r\n * <HealthStatusSection healthCheck={healthCheckWithCache} />\r\n */\r\nexport default function HealthStatusSection({ healthCheck }) {\r\n const context = useGovernance();\r\n const [status, setStatus] = useState({});\r\n const [loading, setLoading] = useState(true);\r\n const [lastCheck, setLastCheck] = useState(null);\r\n\r\n // 🆕 Fallback: props > context\r\n const healthCheckFn = healthCheck || context?.healthCheck;\r\n\r\n const runHealthChecks = async (forceRefresh = false) => {\r\n if (!healthCheckFn) {\r\n console.warn('HealthStatusSection: healthCheck function not provided');\r\n setLoading(false);\r\n return;\r\n }\r\n \r\n setLoading(true);\r\n try {\r\n const results = await healthCheckFn(forceRefresh);\r\n setStatus(results);\r\n setLastCheck(new Date());\r\n } catch (error) {\r\n console.error('Health check failed:', error);\r\n } finally {\r\n setLoading(false);\r\n }\r\n };\r\n\r\n useEffect(() => {\r\n runHealthChecks();\r\n }, [healthCheckFn]);\r\n\r\n const getStatusIcon = (serviceStatus) => {\r\n if (loading && !lastCheck) return '🟡';\r\n \r\n switch (serviceStatus) {\r\n case 'online':\r\n return '🟢';\r\n case 'offline':\r\n return '🔴';\r\n case 'timeout':\r\n return '🟠';\r\n default:\r\n return '🟡';\r\n }\r\n };\r\n\r\n const getStatusLabel = (serviceStatus) => {\r\n switch (serviceStatus) {\r\n case 'online':\r\n return 'Online';\r\n case 'offline':\r\n return 'Offline';\r\n case 'timeout':\r\n return 'Timeout';\r\n default:\r\n return 'Verificando...';\r\n }\r\n };\r\n\r\n const services = [\r\n { id: 'studio', label: 'Supabase Studio' },\r\n { id: 'database', label: 'Database (Kong)' },\r\n { id: 'mailpit', label: 'Mailpit' },\r\n { id: 'mcp', label: 'MCP Server' },\r\n { id: 'functions', label: 'Edge Functions' }\r\n ];\r\n\r\n const allOffline = Object.values(status).every(s => s === 'offline');\r\n const allOnline = Object.values(status).every(s => s === 'online');\r\n\r\n return (\r\n <div className=\"space-y-4\">\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-2xl\">🩺</span>\r\n <h2 className=\"text-xl font-semibold text-slate-100\">Health Status</h2>\r\n </div>\r\n <button\r\n onClick={() => runHealthChecks(true)}\r\n disabled={loading}\r\n className={`flex items-center gap-2 px-3 py-1.5 text-sm bg-slate-700 hover:bg-slate-600 text-slate-200 rounded-lg transition-colors ${\r\n loading ? 'opacity-50 cursor-not-allowed' : ''\r\n }`}\r\n title=\"Verificar novamente\"\r\n >\r\n <RefreshCw className={`w-4 h-4 ${loading ? 'animate-spin' : ''}`} />\r\n Verificar\r\n </button>\r\n </div>\r\n\r\n {/* Banner de Status Geral */}\r\n {allOffline && lastCheck && (\r\n <div className=\"bg-red-500/10 border border-red-500/30 rounded-lg p-4\">\r\n <p className=\"text-red-300 text-sm flex items-center gap-2\">\r\n <span className=\"text-lg\">🔴</span>\r\n <span>\r\n <strong>Supabase Offline:</strong> Execute{' '}\r\n <code className=\"bg-red-900/30 px-1.5 py-0.5 rounded\">npx supabase start</code>\r\n {' '}para iniciar os serviços locais.\r\n </span>\r\n </p>\r\n </div>\r\n )}\r\n\r\n {allOnline && lastCheck && (\r\n <div className=\"bg-green-500/10 border border-green-500/30 rounded-lg p-3\">\r\n <p className=\"text-green-300 text-sm flex items-center gap-2\">\r\n <span className=\"text-lg\">✅</span>\r\n <strong>Todos os serviços online</strong>\r\n </p>\r\n </div>\r\n )}\r\n\r\n {/* Grid de Status */}\r\n <div className=\"bg-slate-800 p-6 rounded-lg border border-slate-700\">\r\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-3\">\r\n {services.map((service) => {\r\n const serviceStatus = status[service.id] || 'checking';\r\n const icon = getStatusIcon(serviceStatus);\r\n const label = getStatusLabel(serviceStatus);\r\n\r\n return (\r\n <div\r\n key={service.id}\r\n className=\"flex items-center justify-between p-3 bg-slate-900 rounded-lg border border-slate-700\"\r\n >\r\n <span className=\"text-sm text-slate-300\">{service.label}</span>\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-lg\">{icon}</span>\r\n <span className=\"text-xs text-slate-400\">{label}</span>\r\n </div>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n\r\n {/* Timestamp */}\r\n {lastCheck && (\r\n <p className=\"mt-4 text-xs text-slate-500 text-center\">\r\n Última verificação: {lastCheck.toLocaleTimeString('pt-BR')}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { Copy, Check } from 'lucide-react';\r\nimport { useState } from 'react';\r\nimport { useGovernance } from '../../contexts/GovernanceContext';\r\n\r\n/**\r\n * Seção de endpoints de API.\r\n *\r\n * @param {Object} props\r\n * @param {Array} props.endpoints - Lista de endpoints de API\r\n * @param {string} props.endpoints[].id - ID único do endpoint\r\n * @param {string} props.endpoints[].name - Nome do endpoint\r\n * @param {string} props.endpoints[].url - URL do endpoint\r\n * @param {string} [props.endpoints[].description] - Descrição do endpoint\r\n * @param {Function} [props.onCopy] - Callback para copiar URLs\r\n *\r\n * @example\r\n * const endpoints = [\r\n * {\r\n * id: 'rest',\r\n * name: 'REST API',\r\n * url: 'http://localhost:54321',\r\n * description: 'REST API endpoint'\r\n * },\r\n * {\r\n * id: 'graphql',\r\n * name: 'GraphQL',\r\n * url: 'http://localhost:54321/graphql/v1',\r\n * description: 'GraphQL API endpoint'\r\n * }\r\n * ];\r\n *\r\n * <APIsSection endpoints={endpoints} onCopy={copyToClipboard} />\r\n */\r\nexport default function APIsSection({ endpoints, onCopy }) {\r\n const context = useGovernance();\r\n const [copiedId, setCopiedId] = useState(null);\r\n\r\n // 🆕 Fallback: props > context > default\r\n const copyFn = onCopy || context?.utils?.copyToClipboard;\r\n\r\n const handleCopy = async (url, id) => {\r\n try {\r\n if (copyFn) {\r\n await copyFn(url);\r\n } else {\r\n // Fallback: API nativa do navegador\r\n await navigator.clipboard.writeText(url);\r\n }\r\n \r\n setCopiedId(id);\r\n setTimeout(() => setCopiedId(null), 2000);\r\n } catch (error) {\r\n console.error('Erro ao copiar:', error);\r\n alert('Erro ao copiar URL');\r\n }\r\n };\r\n\r\n return (\r\n <div className=\"space-y-4\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-2xl\">🌐</span>\r\n <h2 className=\"text-xl font-semibold text-slate-100\">APIs</h2>\r\n </div>\r\n\r\n <div className=\"bg-slate-800 p-6 rounded-lg border border-slate-700 space-y-3\">\r\n {endpoints.map((api) => (\r\n <div\r\n key={api.id}\r\n className=\"p-4 bg-slate-900 rounded-lg border border-slate-700 hover:border-slate-600 transition-colors\"\r\n >\r\n <div className=\"flex items-start justify-between mb-2\">\r\n <div>\r\n <h3 className=\"font-semibold text-slate-100\">{api.name}</h3>\r\n <p className=\"text-xs text-slate-400 mt-0.5\">{api.description}</p>\r\n </div>\r\n <button\r\n onClick={() => handleCopy(api.url, api.id)}\r\n className=\"p-2 text-slate-400 hover:text-slate-200 hover:bg-slate-700 rounded transition-colors flex-shrink-0\"\r\n title=\"Copiar URL\"\r\n >\r\n {copiedId === api.id ? (\r\n <Check className=\"w-4 h-4 text-green-400\" />\r\n ) : (\r\n <Copy className=\"w-4 h-4\" />\r\n )}\r\n </button>\r\n </div>\r\n <code className=\"text-xs text-slate-300 bg-slate-800 px-2 py-1 rounded block truncate\">\r\n {api.url}\r\n </code>\r\n </div>\r\n ))}\r\n\r\n {/* Info adicional */}\r\n <div className=\"pt-4 border-t border-slate-700\">\r\n <p className=\"text-xs text-slate-400\">\r\n <strong className=\"text-slate-300\">Headers obrigatórios:</strong>\r\n </p>\r\n <ul className=\"text-xs text-slate-400 space-y-1 mt-2\">\r\n <li className=\"flex items-start gap-2\">\r\n <span>•</span>\r\n <span>\r\n <code className=\"bg-slate-800 px-1.5 py-0.5 rounded text-slate-300\">apikey</code>\r\n {' '}: Anon Key ou Service Role Key\r\n </span>\r\n </li>\r\n <li className=\"flex items-start gap-2\">\r\n <span>•</span>\r\n <span>\r\n <code className=\"bg-slate-800 px-1.5 py-0.5 rounded text-slate-300\">Authorization</code>\r\n {' '}: Bearer [seu-token-jwt]\r\n </span>\r\n </li>\r\n </ul>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { Database, Copy, Check } from 'lucide-react';\r\nimport { useState } from 'react';\r\nimport { useGovernance } from '../../contexts/GovernanceContext';\r\n\r\n/**\r\n * Seção de configuração do banco de dados.\r\n *\r\n * @param {Object} props\r\n * @param {Object} props.config - Configuração do banco\r\n * @param {string} props.config.host - Host do banco de dados\r\n * @param {number} props.config.port - Porta do banco de dados\r\n * @param {string} props.config.database - Nome do banco de dados\r\n * @param {string} props.config.user - Usuário do banco de dados\r\n * @param {string} props.config.connectionString - String de conexão completa\r\n * @param {Function} [props.onCopy] - Callback para copiar (passado para CredentialField)\r\n * @param {string} [props.databaseStatus='checking'] - Status do banco: 'online' | 'offline' | 'checking'\r\n *\r\n * @example\r\n * const dbConfig = {\r\n * host: 'localhost',\r\n * port: 54322,\r\n * database: 'postgres',\r\n * user: 'postgres',\r\n * connectionString: 'postgresql://postgres:postgres@localhost:54322/postgres'\r\n * };\r\n *\r\n * <DatabaseSection config={dbConfig} onCopy={copyToClipboard} />\r\n */\r\nexport default function DatabaseSection({\r\n config,\r\n onCopy,\r\n databaseStatus = 'checking'\r\n}) {\r\n const context = useGovernance();\r\n const [copied, setCopied] = useState(false);\r\n \r\n // 🆕 Fallback: props > context > default\r\n const copyFn = onCopy || context?.utils?.copyToClipboard;\r\n\r\n const handleCopyConnectionString = async () => {\r\n try {\r\n if (copyFn) {\r\n await copyFn(config.connectionString);\r\n } else {\r\n // Fallback: API nativa do navegador\r\n await navigator.clipboard.writeText(config.connectionString);\r\n }\r\n \r\n setCopied(true);\r\n setTimeout(() => setCopied(false), 2000);\r\n } catch (error) {\r\n console.error('Erro ao copiar:', error);\r\n alert('Erro ao copiar connection string');\r\n }\r\n };\r\n\r\n const getStatusConfig = () => {\r\n switch (databaseStatus) {\r\n case 'online':\r\n return {\r\n badge: '🟢 Online',\r\n bgColor: 'bg-green-500/10',\r\n borderColor: 'border-green-500/30',\r\n textColor: 'text-green-400'\r\n };\r\n case 'offline':\r\n return {\r\n badge: '🔴 Offline',\r\n bgColor: 'bg-red-500/10',\r\n borderColor: 'border-red-500/30',\r\n textColor: 'text-red-400'\r\n };\r\n default:\r\n return {\r\n badge: '🟡 Verificando...',\r\n bgColor: 'bg-yellow-500/10',\r\n borderColor: 'border-yellow-500/30',\r\n textColor: 'text-yellow-400'\r\n };\r\n }\r\n };\r\n\r\n const statusConfig = getStatusConfig();\r\n\r\n return (\r\n <div className=\"space-y-4\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-2xl\">🗄️</span>\r\n <h2 className=\"text-xl font-semibold text-slate-100\">Database</h2>\r\n </div>\r\n\r\n <div className={`rounded-lg border ${statusConfig.borderColor} ${statusConfig.bgColor} p-6`}>\r\n {/* Status Badge */}\r\n <div className=\"flex items-center justify-between mb-4\">\r\n <div className=\"flex items-center gap-2\">\r\n <Database className=\"w-5 h-5 text-slate-300\" />\r\n <span className=\"font-medium text-slate-100\">PostgreSQL</span>\r\n </div>\r\n <span className={`text-xs font-medium px-2 py-1 rounded ${statusConfig.textColor}`}>\r\n {statusConfig.badge}\r\n </span>\r\n </div>\r\n\r\n {/* Database Info */}\r\n <div className=\"space-y-3\">\r\n <div className=\"grid grid-cols-2 gap-3 text-sm\">\r\n <div>\r\n <span className=\"text-slate-400\">Host:</span>\r\n <span className=\"ml-2 text-slate-200\">{config.host}</span>\r\n </div>\r\n <div>\r\n <span className=\"text-slate-400\">Port:</span>\r\n <span className=\"ml-2 text-slate-200\">{config.port}</span>\r\n </div>\r\n <div>\r\n <span className=\"text-slate-400\">Database:</span>\r\n <span className=\"ml-2 text-slate-200\">{config.database}</span>\r\n </div>\r\n <div>\r\n <span className=\"text-slate-400\">User:</span>\r\n <span className=\"ml-2 text-slate-200\">{config.user}</span>\r\n </div>\r\n </div>\r\n\r\n {/* Connection String */}\r\n <div className=\"pt-3 border-t border-slate-700\">\r\n <label className=\"text-sm font-medium text-slate-300 mb-2 block\">\r\n Connection String\r\n </label>\r\n <div className=\"flex items-center gap-2\">\r\n <code className=\"flex-1 text-xs text-slate-300 bg-slate-800 px-3 py-2 rounded border border-slate-700 truncate\">\r\n {config.connectionString}\r\n </code>\r\n <button\r\n onClick={handleCopyConnectionString}\r\n className=\"p-2 text-slate-400 hover:text-slate-200 hover:bg-slate-700 rounded transition-colors flex-shrink-0\"\r\n title=\"Copiar connection string\"\r\n >\r\n {copied ? (\r\n <Check className=\"w-4 h-4 text-green-400\" />\r\n ) : (\r\n <Copy className=\"w-4 h-4\" />\r\n )}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Informações adicionais */}\r\n <div className=\"pt-3 border-t border-slate-700\">\r\n <p className=\"text-xs text-slate-400\">\r\n <strong className=\"text-slate-300\">Conectar via CLI:</strong>\r\n </p>\r\n <code className=\"text-xs text-slate-300 bg-slate-800 px-2 py-1 rounded block mt-2\">\r\n psql {config.connectionString}\r\n </code>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { useState, useEffect } from 'react';\r\nimport { useGovernance } from '../../contexts/GovernanceContext';\r\nimport DevToolsSection from '../supabase/DevToolsSection';\r\nimport AuthKeysSection from '../supabase/AuthKeysSection';\r\nimport HealthStatusSection from '../supabase/HealthStatusSection';\r\nimport APIsSection from '../supabase/APIsSection';\r\nimport DatabaseSection from '../supabase/DatabaseSection';\r\n\r\n/**\r\n * Aba Supabase - Dashboard de desenvolvimento local.\r\n * Exibe informações de serviços, credenciais e health checks.\r\n *\r\n * @param {Object} props\r\n * @param {Function} [props.healthCheck] - Função para verificar health dos serviços\r\n * @param {Object} [props.config] - Configurações do Supabase (database, apis, tools)\r\n * @param {Function} [props.onCopy] - Callback para copiar credenciais\r\n *\r\n * @example\r\n * <SupabaseTab\r\n * healthCheck={healthCheckWithCache}\r\n * config={{ database: {...}, apis: [...], tools: [...] }}\r\n * onCopy={copyToClipboard}\r\n * />\r\n */\r\nexport default function SupabaseTab({ healthCheck, config, onCopy }) {\r\n const context = useGovernance();\r\n const [healthStatus, setHealthStatus] = useState({});\r\n\r\n // 🆕 Fallbacks: props > context\r\n const healthCheckFn = healthCheck || context?.healthCheck;\r\n const finalConfig = config || context?.config?.supabase;\r\n const copyFn = onCopy || context?.utils?.copyToClipboard;\r\n\r\n // Carrega health status inicial\r\n useEffect(() => {\r\n if (!healthCheckFn) return;\r\n \r\n const loadHealthStatus = async () => {\r\n try {\r\n const status = await healthCheckFn();\r\n setHealthStatus(status);\r\n } catch (error) {\r\n console.error('Erro ao carregar health status:', error);\r\n }\r\n };\r\n\r\n loadHealthStatus();\r\n\r\n // Atualiza a cada 30 segundos\r\n const interval = setInterval(loadHealthStatus, 30000);\r\n\r\n return () => clearInterval(interval);\r\n }, [healthCheckFn]);\r\n\r\n return (\r\n <div className=\"space-y-6 pb-8\">\r\n {/* Banner de Aviso - Ambiente de Desenvolvimento */}\r\n <div className=\"bg-amber-500/10 border border-amber-500/30 rounded-lg p-4\">\r\n <p className=\"text-amber-300 text-sm flex items-center gap-2\">\r\n <span className=\"text-xl\">⚠️</span>\r\n <span>\r\n <strong>Ambiente de Desenvolvimento Local</strong> - \r\n Esta aba exibe informações do Supabase rodando em localhost. \r\n Não é visível em produção.\r\n </span>\r\n </p>\r\n </div>\r\n\r\n {/* Development Tools */}\r\n {finalConfig?.tools && <DevToolsSection tools={finalConfig.tools} healthStatus={healthStatus} />}\r\n\r\n {/* Authentication Keys */}\r\n <AuthKeysSection />\r\n\r\n {/* Health Status */}\r\n <HealthStatusSection healthCheck={healthCheckFn} />\r\n\r\n {/* APIs */}\r\n {finalConfig?.apis && <APIsSection endpoints={finalConfig.apis} onCopy={copyFn} />}\r\n\r\n {/* Database */}\r\n {finalConfig?.database && (\r\n <DatabaseSection\r\n config={finalConfig.database}\r\n onCopy={copyFn}\r\n databaseStatus={healthStatus.database}\r\n />\r\n )}\r\n\r\n {/* Footer Info */}\r\n <div className=\"bg-slate-800 border border-slate-700 rounded-lg p-4\">\r\n <p className=\"text-xs text-slate-400 text-center\">\r\n 💡 <strong>Dica:</strong> Para iniciar o Supabase local, execute{' '}\r\n <code className=\"bg-slate-900 px-1.5 py-0.5 rounded text-slate-300\">npx supabase start</code>\r\n {' '}no terminal.\r\n </p>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","// ============================================================================\r\n// AI SETTINGS TAB - Configurações do OpenRouter AI\r\n// ============================================================================\r\n// Interface administrativa para configurar modelos, parâmetros e limites\r\n// Data: 2026-01-13\r\n\r\nimport { useState, useEffect } from 'react';\r\n\r\n/**\r\n * AISettingsTab - Interface de configuração do AI Assistant\r\n * Permite ajustar modelos, parâmetros, rate limits e testar API key\r\n */\r\nexport function AISettingsTab() {\r\n // ──────────────────────────────────────────────────────────────────────\r\n // STATE\r\n // ──────────────────────────────────────────────────────────────────────\r\n const [apiKeyStatus, setApiKeyStatus] = useState('checking'); // checking, valid, invalid, missing\r\n const [apiKeyPreview, setApiKeyPreview] = useState('');\r\n const [testing, setTesting] = useState(false);\r\n \r\n // Configurações de modelo\r\n const [selectedModel, setSelectedModel] = useState('anthropic/claude-sonnet-4');\r\n const [temperature, setTemperature] = useState(0.3);\r\n const [maxTokens, setMaxTokens] = useState(2000);\r\n \r\n // Rate limits\r\n const [rateLimits, setRateLimits] = useState({\r\n dev: 50,\r\n user: 20,\r\n admin: -1\r\n });\r\n \r\n const [maxCosts, setMaxCosts] = useState({\r\n dev: 1.50,\r\n user: 0.50,\r\n admin: -1\r\n });\r\n\r\n // ──────────────────────────────────────────────────────────────────────\r\n // MODELS DATABASE\r\n // ──────────────────────────────────────────────────────────────────────\r\n const availableModels = [\r\n {\r\n id: 'anthropic/claude-sonnet-4',\r\n name: 'Claude Sonnet 4',\r\n provider: 'Anthropic',\r\n speed: 3,\r\n quality: 5,\r\n cost: 3,\r\n contextWindow: 200000,\r\n pricing: { prompt: 3.00, completion: 15.00 },\r\n description: 'Excelente para análise de código e arquitetura'\r\n },\r\n {\r\n id: 'anthropic/claude-opus-4',\r\n name: 'Claude Opus 4',\r\n provider: 'Anthropic',\r\n speed: 2,\r\n quality: 5,\r\n cost: 5,\r\n contextWindow: 200000,\r\n pricing: { prompt: 15.00, completion: 75.00 },\r\n description: 'Máxima qualidade para tarefas complexas'\r\n },\r\n {\r\n id: 'openai/gpt-4-turbo',\r\n name: 'GPT-4 Turbo',\r\n provider: 'OpenAI',\r\n speed: 3,\r\n quality: 5,\r\n cost: 4,\r\n contextWindow: 128000,\r\n pricing: { prompt: 10.00, completion: 30.00 },\r\n description: 'Precisão alta e confiável'\r\n },\r\n {\r\n id: 'openai/gpt-4o',\r\n name: 'GPT-4o',\r\n provider: 'OpenAI',\r\n speed: 4,\r\n quality: 5,\r\n cost: 2,\r\n contextWindow: 128000,\r\n pricing: { prompt: 2.50, completion: 10.00 },\r\n description: 'Rápido e custo-benefício excelente'\r\n },\r\n {\r\n id: 'openai/gpt-4o-mini',\r\n name: 'GPT-4o Mini',\r\n provider: 'OpenAI',\r\n speed: 5,\r\n quality: 4,\r\n cost: 1,\r\n contextWindow: 128000,\r\n pricing: { prompt: 0.15, completion: 0.60 },\r\n description: 'Muito econômico para alto volume'\r\n },\r\n {\r\n id: 'google/gemini-pro-1.5',\r\n name: 'Gemini Pro 1.5',\r\n provider: 'Google',\r\n speed: 4,\r\n quality: 4,\r\n cost: 2,\r\n contextWindow: 1000000,\r\n pricing: { prompt: 1.25, completion: 5.00 },\r\n description: 'Contexto gigante e bom custo-benefício'\r\n },\r\n {\r\n id: 'google/gemini-flash-1.5',\r\n name: 'Gemini Flash 1.5',\r\n provider: 'Google',\r\n speed: 5,\r\n quality: 3,\r\n cost: 1,\r\n contextWindow: 1000000,\r\n pricing: { prompt: 0.075, completion: 0.30 },\r\n description: 'Ultra rápido e econômico'\r\n },\r\n {\r\n id: 'meta-llama/llama-3.3-70b-instruct',\r\n name: 'Llama 3.3 70B',\r\n provider: 'Meta',\r\n speed: 4,\r\n quality: 4,\r\n cost: 1,\r\n contextWindow: 131072,\r\n pricing: { prompt: 0.52, completion: 0.68 },\r\n description: 'Open-source e econômico'\r\n },\r\n {\r\n id: 'meta-llama/llama-3.3-70b-instruct:free',\r\n name: 'Llama 3.3 70B (Free)',\r\n provider: 'Meta',\r\n speed: 3,\r\n quality: 4,\r\n cost: 0,\r\n contextWindow: 131072,\r\n pricing: { prompt: 0.00, completion: 0.00 },\r\n description: 'Gratuito! Ideal para testes'\r\n }\r\n ];\r\n\r\n // ──────────────────────────────────────────────────────────────────────\r\n // EFFECTS\r\n // ──────────────────────────────────────────────────────────────────────\r\n useEffect(() => {\r\n checkApiKeyStatus();\r\n }, []);\r\n\r\n // ──────────────────────────────────────────────────────────────────────\r\n // FUNCTIONS\r\n // ──────────────────────────────────────────────────────────────────────\r\n \r\n async function checkApiKeyStatus() {\r\n try {\r\n // Simulação - em produção, faria chamada real para Edge Function\r\n const hasKey = import.meta.env.OPENROUTER_API_KEY || false;\r\n \r\n if (!hasKey) {\r\n setApiKeyStatus('missing');\r\n setApiKeyPreview('Não configurada');\r\n } else {\r\n setApiKeyStatus('unknown');\r\n setApiKeyPreview('sk-or-v1-••••••••••••••••');\r\n }\r\n } catch (error) {\r\n setApiKeyStatus('invalid');\r\n }\r\n }\r\n\r\n async function testApiKey() {\r\n setTesting(true);\r\n try {\r\n // Chamada de teste para Edge Function\r\n const response = await fetch('http://localhost:54321/functions/v1/openrouter-ai-service', {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({\r\n message: 'test',\r\n context: 'dev',\r\n stream: false\r\n })\r\n });\r\n\r\n if (response.ok) {\r\n setApiKeyStatus('valid');\r\n alert('✅ API Key válida e funcionando!');\r\n } else {\r\n setApiKeyStatus('invalid');\r\n const error = await response.json();\r\n alert('❌ Erro: ' + (error.error?.message || 'API Key inválida'));\r\n }\r\n } catch (error) {\r\n setApiKeyStatus('invalid');\r\n alert('❌ Erro ao testar: ' + error.message);\r\n } finally {\r\n setTesting(false);\r\n }\r\n }\r\n\r\n function estimateCostPerMessage(modelId) {\r\n const model = availableModels.find(m => m.id === modelId);\r\n if (!model) return 0;\r\n\r\n // Estimativa: 1000 tokens prompt + 500 tokens completion\r\n const promptCost = (1000 / 1_000_000) * model.pricing.prompt;\r\n const completionCost = (500 / 1_000_000) * model.pricing.completion;\r\n \r\n return (promptCost + completionCost).toFixed(4);\r\n }\r\n\r\n function getStars(value) {\r\n return '⭐'.repeat(value);\r\n }\r\n\r\n function getCostLabel(cost) {\r\n return '💰'.repeat(cost);\r\n }\r\n\r\n // ──────────────────────────────────────────────────────────────────────\r\n // RENDER\r\n // ──────────────────────────────────────────────────────────────────────\r\n \r\n const selectedModelData = availableModels.find(m => m.id === selectedModel);\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* ────────────────────────────────────────────────────────────── */}\r\n {/* HEADER */}\r\n {/* ────────────────────────────────────────────────────────────── */}\r\n <div>\r\n <h2 className=\"text-2xl font-bold text-gray-900\">⚙️ Configurações do AI Assistant</h2>\r\n <p className=\"text-gray-600\">Configure modelos, parâmetros e limites do OpenRouter</p>\r\n </div>\r\n\r\n {/* ────────────────────────────────────────────────────────────── */}\r\n {/* API KEY STATUS */}\r\n {/* ────────────────────────────────────────────────────────────── */}\r\n <div className={`p-4 rounded-lg border-2 ${\r\n apiKeyStatus === 'valid' ? 'bg-green-50 border-green-200' :\r\n apiKeyStatus === 'invalid' ? 'bg-red-50 border-red-200' :\r\n apiKeyStatus === 'missing' ? 'bg-yellow-50 border-yellow-200' :\r\n 'bg-gray-50 border-gray-200'\r\n }`}>\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <h3 className=\"font-semibold text-gray-900 mb-1\">\r\n {apiKeyStatus === 'valid' && '✅ API Key Válida'}\r\n {apiKeyStatus === 'invalid' && '❌ API Key Inválida'}\r\n {apiKeyStatus === 'missing' && '⚠️ API Key Não Configurada'}\r\n {apiKeyStatus === 'unknown' && '🔍 API Key Status'}\r\n {apiKeyStatus === 'checking' && '⏳ Verificando...'}\r\n </h3>\r\n <p className=\"text-sm text-gray-600 font-mono\">{apiKeyPreview}</p>\r\n {apiKeyStatus === 'missing' && (\r\n <p className=\"text-sm text-orange-700 mt-2\">\r\n Configure <code className=\"bg-orange-100 px-1 rounded\">OPENROUTER_API_KEY</code> no arquivo <code className=\"bg-orange-100 px-1 rounded\">.env</code>\r\n </p>\r\n )}\r\n </div>\r\n <button\r\n onClick={testApiKey}\r\n disabled={testing || apiKeyStatus === 'missing'}\r\n className=\"px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors disabled:bg-gray-300 disabled:cursor-not-allowed\"\r\n >\r\n {testing ? '🔄 Testando...' : '🧪 Testar API Key'}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* ────────────────────────────────────────────────────────────── */}\r\n {/* MODEL SELECTOR */}\r\n {/* ────────────────────────────────────────────────────────────── */}\r\n <div className=\"bg-white rounded-lg border border-gray-200 p-6\">\r\n <h3 className=\"text-lg font-semibold text-gray-900 mb-4\">🤖 Seleção de Modelo</h3>\r\n \r\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">\r\n {availableModels.map(model => (\r\n <button\r\n key={model.id}\r\n onClick={() => setSelectedModel(model.id)}\r\n className={`p-4 rounded-lg border-2 text-left transition-all ${\r\n selectedModel === model.id\r\n ? 'border-blue-500 bg-blue-50'\r\n : 'border-gray-200 hover:border-blue-300'\r\n }`}\r\n >\r\n <div className=\"flex items-start justify-between mb-2\">\r\n <div>\r\n <p className=\"font-semibold text-gray-900\">{model.name}</p>\r\n <p className=\"text-xs text-gray-500\">{model.provider}</p>\r\n </div>\r\n {selectedModel === model.id && <div className=\"text-blue-600\">✓</div>}\r\n </div>\r\n \r\n <p className=\"text-xs text-gray-600 mb-3\">{model.description}</p>\r\n \r\n <div className=\"space-y-1 text-xs\">\r\n <div className=\"flex justify-between\">\r\n <span className=\"text-gray-600\">Velocidade:</span>\r\n <span>{getStars(model.speed)}</span>\r\n </div>\r\n <div className=\"flex justify-between\">\r\n <span className=\"text-gray-600\">Qualidade:</span>\r\n <span>{getStars(model.quality)}</span>\r\n </div>\r\n <div className=\"flex justify-between\">\r\n <span className=\"text-gray-600\">Custo:</span>\r\n <span>{getCostLabel(model.cost) || '🆓 GRÁTIS'}</span>\r\n </div>\r\n <div className=\"flex justify-between items-center mt-2 pt-2 border-t border-gray-200\">\r\n <span className=\"text-gray-600\">$/msg:</span>\r\n <span className=\"font-semibold text-green-600\">\r\n ${estimateCostPerMessage(model.id)}\r\n </span>\r\n </div>\r\n </div>\r\n </button>\r\n ))}\r\n </div>\r\n\r\n {/* Selected Model Details */}\r\n {selectedModelData && (\r\n <div className=\"mt-4 p-4 bg-blue-50 rounded-lg\">\r\n <h4 className=\"font-semibold text-blue-900 mb-2\">Modelo Selecionado: {selectedModelData.name}</h4>\r\n <div className=\"grid grid-cols-2 gap-4 text-sm\">\r\n <div>\r\n <span className=\"text-blue-700\">Context Window:</span>\r\n <span className=\"ml-2 font-semibold\">{selectedModelData.contextWindow.toLocaleString()} tokens</span>\r\n </div>\r\n <div>\r\n <span className=\"text-blue-700\">Preço Prompt:</span>\r\n <span className=\"ml-2 font-semibold\">${selectedModelData.pricing.prompt}/1M tokens</span>\r\n </div>\r\n <div>\r\n <span className=\"text-blue-700\">Preço Completion:</span>\r\n <span className=\"ml-2 font-semibold\">${selectedModelData.pricing.completion}/1M tokens</span>\r\n </div>\r\n <div>\r\n <span className=\"text-blue-700\">Estimativa/msg:</span>\r\n <span className=\"ml-2 font-semibold text-green-600\">${estimateCostPerMessage(selectedModelData.id)}</span>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* ────────────────────────────────────────────────────────────── */}\r\n {/* MODEL PARAMETERS */}\r\n {/* ────────────────────────────────────────────────────────────── */}\r\n <div className=\"bg-white rounded-lg border border-gray-200 p-6\">\r\n <h3 className=\"text-lg font-semibold text-gray-900 mb-4\">🎛️ Parâmetros do Modelo</h3>\r\n \r\n <div className=\"space-y-6\">\r\n {/* Temperature */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-gray-700 mb-2\">\r\n Temperature (Criatividade): {temperature.toFixed(2)}\r\n </label>\r\n <input\r\n type=\"range\"\r\n min=\"0\"\r\n max=\"1\"\r\n step=\"0.05\"\r\n value={temperature}\r\n onChange={(e) => setTemperature(parseFloat(e.target.value))}\r\n className=\"w-full\"\r\n />\r\n <div className=\"flex justify-between text-xs text-gray-500 mt-1\">\r\n <span>0.0 (Preciso)</span>\r\n <span>0.5 (Balanceado)</span>\r\n <span>1.0 (Criativo)</span>\r\n </div>\r\n <p className=\"text-xs text-gray-600 mt-2\">\r\n {temperature < 0.3 && '💼 Ideal para código e análise técnica'}\r\n {temperature >= 0.3 && temperature < 0.7 && '⚖️ Balanceado para uso geral'}\r\n {temperature >= 0.7 && '🎨 Mais criativo e variado'}\r\n </p>\r\n </div>\r\n\r\n {/* Max Tokens */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-gray-700 mb-2\">\r\n Max Tokens (Tamanho da Resposta): {maxTokens}\r\n </label>\r\n <input\r\n type=\"range\"\r\n min=\"500\"\r\n max=\"4000\"\r\n step=\"100\"\r\n value={maxTokens}\r\n onChange={(e) => setMaxTokens(parseInt(e.target.value))}\r\n className=\"w-full\"\r\n />\r\n <div className=\"flex justify-between text-xs text-gray-500 mt-1\">\r\n <span>500 (Curta)</span>\r\n <span>2000 (Média)</span>\r\n <span>4000 (Longa)</span>\r\n </div>\r\n <p className=\"text-xs text-gray-600 mt-2\">\r\n ~{Math.floor(maxTokens / 4)} palavras • ${((maxTokens / 1_000_000) * (selectedModelData?.pricing.completion || 0)).toFixed(4)}/resposta\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* ────────────────────────────────────────────────────────────── */}\r\n {/* RATE LIMITS */}\r\n {/* ────────────────────────────────────────────────────────────── */}\r\n <div className=\"bg-white rounded-lg border border-gray-200 p-6\">\r\n <h3 className=\"text-lg font-semibold text-gray-900 mb-4\">🚦 Rate Limits</h3>\r\n \r\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\r\n {/* Dev */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-gray-700 mb-2\">\r\n 👨‍💻 Desenvolvedores\r\n </label>\r\n <input\r\n type=\"number\"\r\n value={rateLimits.dev}\r\n onChange={(e) => setRateLimits({...rateLimits, dev: parseInt(e.target.value)})}\r\n className=\"w-full px-3 py-2 border border-gray-300 rounded-lg\"\r\n />\r\n <p className=\"text-xs text-gray-500 mt-1\">mensagens/dia</p>\r\n </div>\r\n\r\n {/* User */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-gray-700 mb-2\">\r\n 👤 Usuários\r\n </label>\r\n <input\r\n type=\"number\"\r\n value={rateLimits.user}\r\n onChange={(e) => setRateLimits({...rateLimits, user: parseInt(e.target.value)})}\r\n className=\"w-full px-3 py-2 border border-gray-300 rounded-lg\"\r\n />\r\n <p className=\"text-xs text-gray-500 mt-1\">mensagens/dia</p>\r\n </div>\r\n\r\n {/* Admin */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-gray-700 mb-2\">\r\n 👑 Administradores\r\n </label>\r\n <div className=\"px-3 py-2 bg-gray-100 border border-gray-300 rounded-lg text-center\">\r\n <span className=\"font-semibold\">∞ Ilimitado</span>\r\n </div>\r\n <p className=\"text-xs text-gray-500 mt-1\">sem limite</p>\r\n </div>\r\n </div>\r\n\r\n <div className=\"mt-6 grid grid-cols-1 md:grid-cols-3 gap-4\">\r\n <div>\r\n <label className=\"block text-sm font-medium text-gray-700 mb-2\">\r\n 💰 Custo Máximo/Dia (Dev)\r\n </label>\r\n <input\r\n type=\"number\"\r\n step=\"0.50\"\r\n value={maxCosts.dev}\r\n onChange={(e) => setMaxCosts({...maxCosts, dev: parseFloat(e.target.value)})}\r\n className=\"w-full px-3 py-2 border border-gray-300 rounded-lg\"\r\n />\r\n <p className=\"text-xs text-gray-500 mt-1\">USD/dia</p>\r\n </div>\r\n\r\n <div>\r\n <label className=\"block text-sm font-medium text-gray-700 mb-2\">\r\n 💰 Custo Máximo/Dia (User)\r\n </label>\r\n <input\r\n type=\"number\"\r\n step=\"0.10\"\r\n value={maxCosts.user}\r\n onChange={(e) => setMaxCosts({...maxCosts, user: parseFloat(e.target.value)})}\r\n className=\"w-full px-3 py-2 border border-gray-300 rounded-lg\"\r\n />\r\n <p className=\"text-xs text-gray-500 mt-1\">USD/dia</p>\r\n </div>\r\n\r\n <div>\r\n <label className=\"block text-sm font-medium text-gray-700 mb-2\">\r\n 💰 Custo Máximo/Dia (Admin)\r\n </label>\r\n <div className=\"px-3 py-2 bg-gray-100 border border-gray-300 rounded-lg text-center\">\r\n <span className=\"font-semibold\">∞ Ilimitado</span>\r\n </div>\r\n <p className=\"text-xs text-gray-500 mt-1\">sem limite</p>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* ────────────────────────────────────────────────────────────── */}\r\n {/* SAVE BUTTON */}\r\n {/* ────────────────────────────────────────────────────────────── */}\r\n <div className=\"flex items-center justify-between p-4 bg-blue-50 border border-blue-200 rounded-lg\">\r\n <div>\r\n <p className=\"text-sm text-blue-900 font-semibold\">💡 Configurações Locais</p>\r\n <p className=\"text-xs text-blue-700\">\r\n Estas configurações são apenas visuais. Para aplicar permanentemente, \r\n edite os arquivos de configuração no código.\r\n </p>\r\n </div>\r\n <button\r\n onClick={() => {\r\n console.log('Configurações:', {\r\n model: selectedModel,\r\n temperature,\r\n maxTokens,\r\n rateLimits,\r\n maxCosts\r\n });\r\n alert('💾 Configurações salvas (console)!\\n\\nPara aplicar permanentemente, edite os arquivos de código.');\r\n }}\r\n className=\"px-6 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors font-semibold\"\r\n >\r\n 💾 Salvar no Console\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","// ============================================================================\r\n// AI CONSUMPTION TAB - Admin Dashboard\r\n// ============================================================================\r\n// Visualização de consumo de tokens e custos por usuário\r\n// Permite export CSV e fechamento mensal para cobrança\r\n// Data: 2026-01-13\r\n\r\nimport { useState, useEffect } from 'react';\r\nimport { useGovernance } from '../../contexts/GovernanceContext';\r\n\r\n/**\r\n * AIConsumptionTab - Dashboard de consumo e billing de AI.\r\n *\r\n * @param {Object} props\r\n * @param {Object} [props.client] - Cliente de banco de dados (Supabase client)\r\n * @param {string} [props.tableName='ai_consumption'] - Nome da tabela de consumo\r\n *\r\n * @example\r\n * import { supabase } from './lib/supabase';\r\n *\r\n * <AIConsumptionTab client={supabase} tableName=\"ai_consumption\" />\r\n */\r\nexport function AIConsumptionTab({ client, tableName = 'ai_consumption' }) {\r\n // 🆕 Context\r\n const context = useGovernance();\r\n \r\n // 🆕 Fallback: props > context\r\n const dbClient = client || context?.client;\r\n \r\n // ──────────────────────────────────────────────────────────────────────\r\n // STATE\r\n // ──────────────────────────────────────────────────────────────────────\r\n const [loading, setLoading] = useState(true);\r\n const [selectedMonth, setSelectedMonth] = useState(getCurrentMonth());\r\n const [consumptionData, setConsumptionData] = useState([]);\r\n const [monthlyTotals, setMonthlyTotals] = useState(null);\r\n const [billingStatus, setBillingStatus] = useState(null);\r\n\r\n // ──────────────────────────────────────────────────────────────────────\r\n // EFFECTS\r\n // ──────────────────────────────────────────────────────────────────────\r\n useEffect(() => {\r\n loadConsumptionData();\r\n loadBillingStatus();\r\n }, [selectedMonth]);\r\n\r\n // ──────────────────────────────────────────────────────────────────────\r\n // DATA LOADING\r\n // ──────────────────────────────────────────────────────────────────────\r\n \r\n async function loadConsumptionData() {\r\n if (!dbClient) {\r\n console.warn('AIConsumptionTab: client not provided');\r\n setLoading(false);\r\n return;\r\n }\r\n \r\n try {\r\n setLoading(true);\r\n\r\n // Buscar dados de consumo do mês usando a VIEW\r\n const { data, error } = await dbClient\r\n .from('ai_user_consumption_summary')\r\n .select('*')\r\n .gte('month', `${selectedMonth}-01`)\r\n .lt('month', getNextMonth(selectedMonth))\r\n .order('total_cost_usd', { ascending: false });\r\n\r\n if (error) throw error;\r\n\r\n setConsumptionData(data || []);\r\n\r\n // Calcular totais\r\n const totals = calculateTotals(data || []);\r\n setMonthlyTotals(totals);\r\n\r\n } catch (error) {\r\n console.error('Error loading consumption data:', error);\r\n } finally {\r\n setLoading(false);\r\n }\r\n }\r\n\r\n async function loadBillingStatus() {\r\n if (!dbClient) return;\r\n \r\n try {\r\n // Buscar status de billing do mês\r\n const { data, error } = await dbClient\r\n .from('ai_monthly_billing')\r\n .select('*')\r\n .eq('month', `${selectedMonth}-01`)\r\n .maybeSingle();\r\n\r\n if (error && error.code !== 'PGRST116') throw error; // Ignorar \"not found\"\r\n\r\n setBillingStatus(data);\r\n } catch (error) {\r\n console.error('Error loading billing status:', error);\r\n }\r\n }\r\n\r\n // ──────────────────────────────────────────────────────────────────────\r\n // ACTIONS\r\n // ──────────────────────────────────────────────────────────────────────\r\n \r\n async function handleExportCSV() {\r\n if (!consumptionData.length) return;\r\n\r\n // Preparar dados CSV\r\n const headers = ['Usuário', 'Email', 'Contexto', 'Mensagens', 'Tokens', 'Custo (USD)', 'Dias Ativos'];\r\n const rows = consumptionData.map(row => [\r\n row.user_id,\r\n row.email,\r\n row.context,\r\n row.total_messages,\r\n row.total_tokens,\r\n row.total_cost_usd.toFixed(4),\r\n row.active_days\r\n ]);\r\n\r\n const csvContent = [\r\n headers.join(','),\r\n ...rows.map(row => row.join(','))\r\n ].join('\\n');\r\n\r\n // Download\r\n const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });\r\n const link = document.createElement('a');\r\n link.href = URL.createObjectURL(blob);\r\n link.download = `ai-consumption-${selectedMonth}.csv`;\r\n link.click();\r\n }\r\n\r\n async function handleCloseMonth() {\r\n if (!dbClient) {\r\n alert('Cliente de banco de dados não configurado');\r\n return;\r\n }\r\n \r\n if (!confirm(`Fechar mês ${selectedMonth} para billing?\\n\\nIsso marcará o período como fechado e impedirá alterações.`)) {\r\n return;\r\n }\r\n\r\n try {\r\n setLoading(true);\r\n\r\n // Criar/atualizar registros de billing mensal\r\n const billingRecords = consumptionData.map(row => ({\r\n user_id: row.user_id,\r\n month: `${selectedMonth}-01`,\r\n context: row.context,\r\n total_messages: row.total_messages,\r\n total_tokens: row.total_tokens,\r\n total_cost_usd: row.total_cost_usd,\r\n status: 'closed',\r\n closed_at: new Date().toISOString()\r\n }));\r\n\r\n const { error } = await dbClient\r\n .from('ai_monthly_billing')\r\n .upsert(billingRecords, {\r\n onConflict: 'user_id,month,context'\r\n });\r\n\r\n if (error) throw error;\r\n\r\n alert(`✅ Mês ${selectedMonth} fechado com sucesso!`);\r\n loadBillingStatus();\r\n } catch (error) {\r\n console.error('Error closing month:', error);\r\n alert('Erro ao fechar mês: ' + error.message);\r\n } finally {\r\n setLoading(false);\r\n }\r\n }\r\n\r\n async function handleMarkAsBilled() {\r\n if (!dbClient) {\r\n alert('Cliente de banco de dados não configurado');\r\n return;\r\n }\r\n \r\n if (!confirm(`Marcar mês ${selectedMonth} como faturado?`)) {\r\n return;\r\n }\r\n\r\n try {\r\n const { error } = await dbClient\r\n .from('ai_monthly_billing')\r\n .update({\r\n status: 'billed',\r\n billed_at: new Date().toISOString()\r\n })\r\n .eq('month', `${selectedMonth}-01`);\r\n\r\n if (error) throw error;\r\n\r\n alert('✅ Mês marcado como faturado!');\r\n loadBillingStatus();\r\n } catch (error) {\r\n console.error('Error marking as billed:', error);\r\n alert('Erro: ' + error.message);\r\n }\r\n }\r\n\r\n // ──────────────────────────────────────────────────────────────────────\r\n // RENDER\r\n // ──────────────────────────────────────────────────────────────────────\r\n \r\n if (loading) {\r\n return (\r\n <div className=\"flex items-center justify-center h-64\">\r\n <div className=\"text-center\">\r\n <div className=\"animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto mb-4\"></div>\r\n <p className=\"text-gray-600\">Carregando dados de consumo...</p>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* ────────────────────────────────────────────────────────────── */}\r\n {/* HEADER */}\r\n {/* ────────────────────────────────────────────────────────────── */}\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <h2 className=\"text-2xl font-bold text-gray-900\">💰 Consumo de AI</h2>\r\n <p className=\"text-gray-600\">Monitore o uso de tokens e custos por usuário</p>\r\n </div>\r\n\r\n <div className=\"flex items-center gap-3\">\r\n {/* Seletor de mês */}\r\n <select\r\n value={selectedMonth}\r\n onChange={(e) => setSelectedMonth(e.target.value)}\r\n className=\"px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500\"\r\n >\r\n {getMonthOptions().map(month => (\r\n <option key={month} value={month}>\r\n {formatMonthLabel(month)}\r\n </option>\r\n ))}\r\n </select>\r\n\r\n {/* Export CSV */}\r\n <button\r\n onClick={handleExportCSV}\r\n disabled={!consumptionData.length}\r\n className=\"px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors disabled:bg-gray-300 disabled:cursor-not-allowed\"\r\n >\r\n 📥 Exportar CSV\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* ────────────────────────────────────────────────────────────── */}\r\n {/* BILLING STATUS */}\r\n {/* ────────────────────────────────────────────────────────────── */}\r\n {billingStatus && (\r\n <div className={`p-4 rounded-lg border-2 ${\r\n billingStatus.status === 'open' ? 'bg-blue-50 border-blue-200' :\r\n billingStatus.status === 'closed' ? 'bg-yellow-50 border-yellow-200' :\r\n billingStatus.status === 'billed' ? 'bg-green-50 border-green-200' :\r\n 'bg-gray-50 border-gray-200'\r\n }`}>\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <p className=\"font-semibold text-gray-900\">\r\n Status do Mês: {\r\n billingStatus.status === 'open' ? '🔓 Aberto' :\r\n billingStatus.status === 'closed' ? '🔒 Fechado' :\r\n billingStatus.status === 'billed' ? '✅ Faturado' :\r\n billingStatus.status === 'paid' ? '💰 Pago' :\r\n billingStatus.status\r\n }\r\n </p>\r\n {billingStatus.closed_at && (\r\n <p className=\"text-sm text-gray-600\">\r\n Fechado em: {new Date(billingStatus.closed_at).toLocaleString('pt-BR')}\r\n </p>\r\n )}\r\n </div>\r\n\r\n <div className=\"flex gap-2\">\r\n {billingStatus.status === 'open' && (\r\n <button\r\n onClick={handleCloseMonth}\r\n className=\"px-4 py-2 bg-yellow-600 text-white rounded-lg hover:bg-yellow-700\"\r\n >\r\n 🔒 Fechar Mês\r\n </button>\r\n )}\r\n {billingStatus.status === 'closed' && (\r\n <button\r\n onClick={handleMarkAsBilled}\r\n className=\"px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700\"\r\n >\r\n ✅ Marcar como Faturado\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {!billingStatus && selectedMonth === getCurrentMonth() && (\r\n <div className=\"p-4 bg-blue-50 border border-blue-200 rounded-lg\">\r\n <p className=\"text-blue-900\">\r\n 💡 <strong>Mês atual em andamento.</strong> Feche o mês no último dia para gerar billing.\r\n </p>\r\n </div>\r\n )}\r\n\r\n {/* ────────────────────────────────────────────────────────────── */}\r\n {/* TOTALS SUMMARY */}\r\n {/* ────────────────────────────────────────────────────────────── */}\r\n {monthlyTotals && (\r\n <div className=\"grid grid-cols-1 md:grid-cols-4 gap-4\">\r\n <div className=\"bg-white p-4 rounded-lg border border-gray-200\">\r\n <p className=\"text-sm text-gray-600\">Total de Usuários</p>\r\n <p className=\"text-2xl font-bold text-gray-900\">{monthlyTotals.uniqueUsers}</p>\r\n </div>\r\n <div className=\"bg-white p-4 rounded-lg border border-gray-200\">\r\n <p className=\"text-sm text-gray-600\">Total de Mensagens</p>\r\n <p className=\"text-2xl font-bold text-gray-900\">{monthlyTotals.totalMessages.toLocaleString()}</p>\r\n </div>\r\n <div className=\"bg-white p-4 rounded-lg border border-gray-200\">\r\n <p className=\"text-sm text-gray-600\">Total de Tokens</p>\r\n <p className=\"text-2xl font-bold text-gray-900\">{monthlyTotals.totalTokens.toLocaleString()}</p>\r\n </div>\r\n <div className=\"bg-white p-4 rounded-lg border border-gray-200\">\r\n <p className=\"text-sm text-gray-600\">Custo Total</p>\r\n <p className=\"text-2xl font-bold text-green-600\">\r\n ${monthlyTotals.totalCost.toFixed(2)}\r\n </p>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* ────────────────────────────────────────────────────────────── */}\r\n {/* CONSUMPTION TABLE */}\r\n {/* ────────────────────────────────────────────────────────────── */}\r\n {consumptionData.length > 0 ? (\r\n <div className=\"bg-white rounded-lg border border-gray-200 overflow-hidden\">\r\n <table className=\"w-full\">\r\n <thead className=\"bg-gray-50\">\r\n <tr>\r\n <th className=\"px-4 py-3 text-left text-sm font-semibold text-gray-900\">Usuário</th>\r\n <th className=\"px-4 py-3 text-left text-sm font-semibold text-gray-900\">Contexto</th>\r\n <th className=\"px-4 py-3 text-right text-sm font-semibold text-gray-900\">Mensagens</th>\r\n <th className=\"px-4 py-3 text-right text-sm font-semibold text-gray-900\">Tokens</th>\r\n <th className=\"px-4 py-3 text-right text-sm font-semibold text-gray-900\">Custo (USD)</th>\r\n <th className=\"px-4 py-3 text-right text-sm font-semibold text-gray-900\">Dias Ativos</th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-gray-200\">\r\n {consumptionData.map((row, idx) => (\r\n <tr key={idx} className=\"hover:bg-gray-50\">\r\n <td className=\"px-4 py-3\">\r\n <div>\r\n <p className=\"text-sm font-medium text-gray-900\">{row.email}</p>\r\n <p className=\"text-xs text-gray-500\">{row.user_id.substring(0, 8)}...</p>\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <span className={`px-2 py-1 text-xs rounded-full ${\r\n row.context === 'dev' ? 'bg-blue-100 text-blue-800' :\r\n row.context === 'user' ? 'bg-green-100 text-green-800' :\r\n 'bg-purple-100 text-purple-800'\r\n }`}>\r\n {row.context}\r\n </span>\r\n </td>\r\n <td className=\"px-4 py-3 text-right text-sm text-gray-900\">\r\n {row.total_messages?.toLocaleString() || 0}\r\n </td>\r\n <td className=\"px-4 py-3 text-right text-sm text-gray-900\">\r\n {row.total_tokens?.toLocaleString() || 0}\r\n </td>\r\n <td className=\"px-4 py-3 text-right text-sm font-semibold text-green-600\">\r\n ${(row.total_cost_usd || 0).toFixed(4)}\r\n </td>\r\n <td className=\"px-4 py-3 text-right text-sm text-gray-600\">\r\n {row.active_days || 0}\r\n </td>\r\n </tr>\r\n ))}\r\n </tbody>\r\n </table>\r\n </div>\r\n ) : (\r\n <div className=\"bg-gray-50 rounded-lg p-12 text-center\">\r\n <div className=\"text-6xl mb-4\">📊</div>\r\n <p className=\"text-gray-600\">Nenhum consumo registrado neste mês</p>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\n// ============================================================================\r\n// HELPER FUNCTIONS\r\n// ============================================================================\r\n\r\nfunction getCurrentMonth() {\r\n const now = new Date();\r\n return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`;\r\n}\r\n\r\nfunction getNextMonth(month) {\r\n const [year, m] = month.split('-').map(Number);\r\n const next = m === 12 ? `${year + 1}-01` : `${year}-${String(m + 1).padStart(2, '0')}`;\r\n return next;\r\n}\r\n\r\nfunction getMonthOptions() {\r\n const options = [];\r\n const now = new Date();\r\n \r\n // Últimos 6 meses\r\n for (let i = 5; i >= 0; i--) {\r\n const date = new Date(now.getFullYear(), now.getMonth() - i, 1);\r\n const month = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`;\r\n options.push(month);\r\n }\r\n \r\n return options;\r\n}\r\n\r\nfunction formatMonthLabel(month) {\r\n const [year, m] = month.split('-');\r\n const months = ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'];\r\n return `${months[parseInt(m) - 1]}/${year}`;\r\n}\r\n\r\nfunction calculateTotals(data) {\r\n const uniqueUsers = new Set(data.map(d => d.user_id)).size;\r\n const totalMessages = data.reduce((sum, d) => sum + (d.total_messages || 0), 0);\r\n const totalTokens = data.reduce((sum, d) => sum + (d.total_tokens || 0), 0);\r\n const totalCost = data.reduce((sum, d) => sum + (d.total_cost_usd || 0), 0);\r\n\r\n return { uniqueUsers, totalMessages, totalTokens, totalCost };\r\n}\r\n","// ============================================================================\r\n// DEV ASSISTANT TAB - Dev Dashboard Integration\r\n// ============================================================================\r\n// Aba de AI Assistant no Dev Dashboard (Governance)\r\n// Usa ChatInterface com contexto 'dev'\r\n// Data: 2026-01-13\r\n\r\nimport { useGovernance } from '../../contexts/GovernanceContext';\r\n\r\n/**\r\n * DevAssistantTab - Aba de AI Assistant para desenvolvedores.\r\n *\r\n * @param {Object} props\r\n * @param {React.Component} [props.ChatInterface] - Componente de chat a ser renderizado\r\n * @param {Object} [props.chatConfig] - Configuração do chat (endpoint, context, etc)\r\n *\r\n * @example\r\n * <DevAssistantTab\r\n * ChatInterface={ChatInterface}\r\n * chatConfig={{ endpoint: '...', context: 'dev' }}\r\n * />\r\n */\r\nexport function DevAssistantTab({ ChatInterface, chatConfig }) {\r\n // 🆕 Context\r\n const context = useGovernance();\r\n \r\n // 🆕 Fallbacks: props > context\r\n const ChatComponent = ChatInterface || context?.ChatInterface;\r\n const finalChatConfig = chatConfig || context?.chatConfig;\r\n \r\n // ──────────────────────────────────────────────────────────────────────\r\n // CONFIGURAÇÃO\r\n // ──────────────────────────────────────────────────────────────────────\r\n //const endpoint = import.meta.env.VITE_SUPABASE_URL \r\n // ? `${import.meta.env.VITE_SUPABASE_URL}/functions/v1/openrouter-ai-service`\r\n // : '/api/openrouter-ai-service'; // Fallback para desenvolvimento local\r\n // Linha 18, substituir por:\r\n const endpoint = 'http://localhost:54321/functions/v1/openrouter-ai-service';\r\n\r\n const welcomeMessage = `👋 Olá! Sou o **Nexus Dev Assistant**.\r\n\r\nPosso ajudar você com:\r\n• 🏗️ Arquitetura e design do projeto\r\n• 💻 Localizar código e componentes \r\n• 📋 Explicar PLANs e decisões técnicas\r\n• 🐛 Entender débitos técnicos\r\n• 📊 Consultar logs e histórico\r\n• 🔧 Sugerir padrões e boas práticas\r\n\r\n**Dica:** Seja específico nas suas perguntas para respostas mais precisas!`;\r\n\r\n const suggestedQuestions = [\r\n 'Como funciona o sistema de débitos técnicos?',\r\n 'Onde está o código de autenticação?',\r\n 'Quais migrations foram aplicadas recentemente?',\r\n 'Como funciona o drag and drop no CRM?',\r\n 'Qual é a estrutura de componentes do projeto?',\r\n 'Como criar um novo componente seguindo os padrões?'\r\n ];\r\n\r\n // ──────────────────────────────────────────────────────────────────────\r\n // CALLBACKS (para analytics/métricas futuras)\r\n // ──────────────────────────────────────────────────────────────────────\r\n const handleMessageSent = (message) => {\r\n console.log('[Dev Assistant] Message sent:', message);\r\n // TODO: Trackear métricas (analytics)\r\n };\r\n\r\n const handleResponseReceived = (response) => {\r\n console.log('[Dev Assistant] Response received:', response.substring(0, 100) + '...');\r\n // TODO: Trackear métricas (analytics)\r\n };\r\n\r\n const handleError = (error) => {\r\n console.error('[Dev Assistant] Error:', error);\r\n // TODO: Enviar para error tracking (Sentry, etc)\r\n };\r\n\r\n // ──────────────────────────────────────────────────────────────────────\r\n // RENDER\r\n // ──────────────────────────────────────────────────────────────────────\r\n return (\r\n <div className=\"h-full flex flex-col\">\r\n {/* Header Info */}\r\n <div className=\"mb-4 bg-blue-50 border border-blue-200 rounded-lg p-4\">\r\n <div className=\"flex items-start gap-3\">\r\n <div className=\"text-2xl\">💡</div>\r\n <div className=\"flex-1\">\r\n <h3 className=\"font-semibold text-blue-900 mb-1\">\r\n Como usar o Dev Assistant\r\n </h3>\r\n <ul className=\"text-sm text-blue-800 space-y-1\">\r\n <li>• Faça perguntas sobre a arquitetura, código ou decisões do projeto</li>\r\n <li>• Use sugestões de perguntas para começar rapidamente</li>\r\n <li>• Todas as respostas são baseadas na documentação e código do projeto</li>\r\n <li>• Links clicáveis levam diretamente aos arquivos mencionados</li>\r\n </ul>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Chat Interface */}\r\n <div className=\"flex-1 min-h-0\">\r\n {ChatComponent ? (\r\n <ChatComponent\r\n endpoint={finalChatConfig?.endpoint || endpoint}\r\n context={finalChatConfig?.context || \"dev\"}\r\n defaultModel={finalChatConfig?.defaultModel || \"anthropic/claude-sonnet-4\"}\r\n modelSelectable={finalChatConfig?.modelSelectable || false}\r\n temperature={finalChatConfig?.temperature || 0.3}\r\n placeholder={finalChatConfig?.placeholder || \"Pergunte sobre o projeto...\"}\r\n welcomeMessage={finalChatConfig?.welcomeMessage || welcomeMessage}\r\n suggestedQuestions={finalChatConfig?.suggestedQuestions || suggestedQuestions}\r\n onMessageSent={handleMessageSent}\r\n onResponseReceived={handleResponseReceived}\r\n onError={handleError}\r\n />\r\n ) : (\r\n <div className=\"flex items-center justify-center h-full bg-gray-50 rounded-lg border-2 border-dashed border-gray-300\">\r\n <div className=\"text-center p-8\">\r\n <div className=\"text-6xl mb-4\">💬</div>\r\n <p className=\"text-gray-600 text-lg font-medium mb-2\">\r\n Chat Interface não configurado\r\n </p>\r\n <p className=\"text-gray-500 text-sm\">\r\n Passe o componente ChatInterface via props para habilitar o assistente\r\n </p>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Footer Info */}\r\n <div className=\"mt-4 text-xs text-gray-500 text-center\">\r\n <p>\r\n 💰 Cada pergunta consome créditos da OpenRouter • \r\n 📊 Veja o consumo na aba \"Consumo AI\"\r\n </p>\r\n </div>\r\n </div>\r\n );\r\n}\r\n"],"names":["DashboardLayout","tabs","activeTab","onTabChange","onRefresh","isRefreshing","refreshSuccess","children","navigate","useNavigate","jsxs","jsx","ChevronLeft","Fragment","Check","RefreshCw","tab","MetricCard","title","value","subtitle","icon","trend","trendColors","HealthScore","score","colors","TechStackList","stack","items","item","index","parseTechDebtRegistry","markdownContent","lines","l","debts","line","cols","s","stats","d","parseBacklogRegistry","i","parseArchitectureLog","entries","currentEntry","contentLines","headerMatch","_a","_b","_c","calculateHealthScore","techDebtStats","backlogStats","getCategoryIcon","category","getSeverityIcon","severity","getSeverityName","getSeverityColor","parsePlan","filename","frontmatter","contentStart","match","totalTasks","completedTasks","parseDecisionsLog","_d","parseAllLogs","logsContent","allEntries","archEntries","e","decEntries","a","b","getPriorityColor","priority","getStatusColor","status","formatTimestamp","timestamp","RecentActivityFeed","activities","activity","QuickActionsGrid","actions","FileText","GitBranch","AlertTriangle","Target","colorClasses","action","Icon","OverviewTab","metrics","fetchMarkdown","path","url","response","error","loadTechDebtData","content","loadBacklogData","loadLogsData","architecture","decisions","loadPlansData","knownPlans","calculateProjectMetrics","techDebt","backlog","logs","DebtStats","statCards","card","DebtFilters","filters","onFilterChange","handleSeverityChange","handleStatusChange","handleSearchChange","SeverityBadge","colorClass","countProjectFiles","debounce","func","wait","timeout","args","later","filterBySearchText","searchText","properties","search","prop","groupBy","property","acc","key","copyToClipboard","text","DebtCard","debt","handleCopyId","isResolved","Copy","TechDebtTab","data","setData","useState","filteredDebts","setFilteredDebts","setFilters","loading","setLoading","useEffect","load","result","filtered","BacklogStats","BacklogFilters","handleCategoryChange","CategoryBadge","BacklogItem","statusColor","isDone","BacklogTab","filteredItems","setFilteredItems","MarkdownViewer","className","collapsed","setCollapsed","parseMarkdown","elements","currentList","currentCodeBlock","codeLines","inBlockquote","blockquoteLines","flushList","flushCodeBlock","code","flushBlockquote","idx","sectionId","isCollapsed","prev","formatInlineMarkdown","parts","lastIndex","boldRegex","italicRegex","codeRegex","linkRegex","combined","c","LogEntry","log","isExpanded","setIsExpanded","logTypeColors","logTypeLabels","borderColor","ChevronDown","ChevronRight","LogTimeline","LogFilters","totalLogs","handleTypeChange","LogsTab","setLogs","filteredLogs","setFilteredLogs","limited","ArchitectureTab","setContent","setActiveTab","loadContent","GovernanceContext","createContext","GovernanceProvider","utils","client","config","healthCheck","ChatInterface","chatConfig","useGovernance","useContext","defaultUtils","ServiceCard","name","description","onCopy","context","copied","setCopied","copyFn","handleCopy","handleOpen","statusConfig","isDisabled","ExternalLink","DevToolsSection","tools","healthStatus","tool","CredentialField","label","maskFunction","warning","placeholder","maskFn","isVisible","setIsVisible","toggleVisibility","displayValue","val","hasValue","EyeOff","Eye","AuthKeysSection","HealthStatusSection","setStatus","lastCheck","setLastCheck","healthCheckFn","runHealthChecks","forceRefresh","results","getStatusIcon","serviceStatus","getStatusLabel","services","allOffline","allOnline","service","APIsSection","endpoints","copiedId","setCopiedId","id","api","DatabaseSection","databaseStatus","handleCopyConnectionString","Database","SupabaseTab","setHealthStatus","finalConfig","loadHealthStatus","interval","AISettingsTab","apiKeyStatus","setApiKeyStatus","apiKeyPreview","setApiKeyPreview","testing","setTesting","selectedModel","setSelectedModel","temperature","setTemperature","maxTokens","setMaxTokens","rateLimits","setRateLimits","maxCosts","setMaxCosts","availableModels","checkApiKeyStatus","testApiKey","estimateCostPerMessage","modelId","model","m","promptCost","completionCost","getStars","getCostLabel","cost","selectedModelData","AIConsumptionTab","tableName","dbClient","selectedMonth","setSelectedMonth","getCurrentMonth","consumptionData","setConsumptionData","monthlyTotals","setMonthlyTotals","billingStatus","setBillingStatus","loadConsumptionData","loadBillingStatus","getNextMonth","totals","calculateTotals","handleExportCSV","headers","rows","row","csvContent","blob","link","handleCloseMonth","billingRecords","handleMarkAsBilled","getMonthOptions","month","formatMonthLabel","now","year","options","date","uniqueUsers","totalMessages","sum","totalTokens","totalCost","DevAssistantTab","ChatComponent","finalChatConfig","endpoint","welcomeMessage","suggestedQuestions","handleMessageSent","message","handleResponseReceived","handleError"],"mappings":"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"}