feat: sales opportunity detail, procurement filters, permission resilience

- Add sales opportunity detail page with tabs (overview, notes, contacts, products, forecasts, activity)
- Add sales note CRUD endpoints (create, update, delete) with server routes
- Add opportunity types, contacts, product sequencing, and refresh API methods
- Add AddProductModal component for catalog browsing
- Update procurement.fetchMany to accept CatalogItemFilters object
- Add procurement.fetchCategories and procurement.fetchFilters endpoints
- Add resilient permission check (no-token returns all-true with __checkFailed)
- Parallelize company detail data fetches for performance
- Remove stale console.log statements across modules
- Add comprehensive unit tests for all new API methods and permission edge cases
This commit is contained in:
2026-03-01 13:08:58 -06:00
parent 27755d4a00
commit 4bec198db6
30 changed files with 10810 additions and 83 deletions
+46
View File
@@ -373,11 +373,57 @@
color: var(--status-active-color, #16a34a);
}
.sales-status-badge.status-won {
background: #dbeafe;
color: #2563eb;
}
.sales-status-badge.status-lost {
background: #fef3c7;
color: #d97706;
}
.sales-status-badge.status-inactive {
background: #f3f4f6;
color: #6b7280;
}
.sales-status-badge.status-closed {
background: var(--status-inactive-bg, #fee2e2);
color: var(--status-inactive-color, #dc2626);
}
.sales-status-badge.status-equiv {
border: 1px dashed currentColor;
cursor: default;
position: relative;
}
.sales-status-badge.status-equiv[data-tooltip]::after {
content: attr(data-tooltip);
position: absolute;
bottom: calc(100% + 6px);
left: 50%;
transform: translateX(-50%);
background: var(--tooltip-bg, #1e293b);
color: var(--tooltip-color, #f8fafc);
font-size: 11px;
font-weight: 500;
text-transform: none;
letter-spacing: 0;
white-space: nowrap;
padding: 4px 8px;
border-radius: 5px;
pointer-events: none;
opacity: 0;
transition: opacity 0.15s ease;
z-index: 10;
}
.sales-status-badge.status-equiv[data-tooltip]:hover::after {
opacity: 1;
}
.sales-priority {
font-size: 12px;
font-weight: 600;