added panels

This commit is contained in:
2026-02-10 12:09:38 -07:00
parent 4a50cd100b
commit 0c9c3b5514

View File

@@ -1255,212 +1255,206 @@ export default function App() {
</div> </div>
)} )}
{/* Quick Check */} {/* Three Column Layout */}
<div style={{...STYLES.intelCard, padding: '1.5rem', marginBottom: '1.5rem'}} className="rounded-lg"> <div className="grid grid-cols-12 gap-6">
<div className="scan-line"></div> {/* LEFT PANEL - Wiki/Knowledge Base */}
<h2 style={{ fontSize: '1.125rem', fontWeight: '600', color: '#00D9FF', marginBottom: '0.75rem', fontFamily: 'monospace', textTransform: 'uppercase', letterSpacing: '0.1em', textShadow: '0 0 20px rgba(0, 217, 255, 0.5)' }}>Quick CVE Lookup</h2> <div className="col-span-12 lg:col-span-3 space-y-4">
<div className="flex gap-3"> <div style={{...STYLES.intelCard, padding: '1.5rem', borderLeft: '4px solid #00FF88'}} className="rounded-lg">
<input <h2 style={{ fontSize: '1.125rem', fontWeight: '600', color: '#00FF88', marginBottom: '1rem', fontFamily: 'monospace', textTransform: 'uppercase', letterSpacing: '0.1em', textShadow: '0 0 15px rgba(0, 255, 136, 0.5)' }}>
type="text" Knowledge Base
placeholder="Enter CVE ID (e.g., CVE-2024-1234)" </h2>
value={quickCheckCVE}
onChange={(e) => setQuickCheckCVE(e.target.value)} {/* Wiki/Blog Style Entries */}
onKeyPress={(e) => e.key === 'Enter' && quickCheckCVEStatus()} <div className="space-y-3">
className="flex-1 intel-input" <div style={{ background: 'linear-gradient(135deg, rgba(19, 25, 55, 0.85) 0%, rgba(30, 39, 73, 0.75) 100%)', border: '1px solid rgba(0, 255, 136, 0.3)', borderRadius: '0.375rem', padding: '0.75rem', cursor: 'pointer', transition: 'all 0.2s' }} className="hover:border-intel-success">
/> <h3 className="text-white font-semibold text-sm mb-1 font-mono">CVE Response Procedures</h3>
<button <p className="text-gray-400 text-xs mb-2">Standard operating procedures for vulnerability response and escalation...</p>
onClick={quickCheckCVEStatus} <span className="text-xs text-intel-success font-mono">Last updated: 2024-02-08</span>
className="intel-button intel-button-primary" </div>
>
Scan <div style={{ background: 'linear-gradient(135deg, rgba(19, 25, 55, 0.85) 0%, rgba(30, 39, 73, 0.75) 100%)', border: '1px solid rgba(0, 255, 136, 0.3)', borderRadius: '0.375rem', padding: '0.75rem', cursor: 'pointer', transition: 'all 0.2s' }} className="hover:border-intel-success">
</button> <h3 className="text-white font-semibold text-sm mb-1 font-mono">Vendor Contact Matrix</h3>
<p className="text-gray-400 text-xs mb-2">Emergency contacts and escalation paths for security vendors...</p>
<span className="text-xs text-intel-success font-mono">Last updated: 2024-02-05</span>
</div>
<div style={{ background: 'linear-gradient(135deg, rgba(19, 25, 55, 0.85) 0%, rgba(30, 39, 73, 0.75) 100%)', border: '1px solid rgba(0, 255, 136, 0.3)', borderRadius: '0.375rem', padding: '0.75rem', cursor: 'pointer', transition: 'all 0.2s' }} className="hover:border-intel-success">
<h3 className="text-white font-semibold text-sm mb-1 font-mono">Severity Classification Guide</h3>
<p className="text-gray-400 text-xs mb-2">Guidelines for assessing and classifying vulnerability severity levels...</p>
<span className="text-xs text-intel-success font-mono">Last updated: 2024-01-28</span>
</div>
<div style={{ background: 'linear-gradient(135deg, rgba(19, 25, 55, 0.85) 0%, rgba(30, 39, 73, 0.75) 100%)', border: '1px solid rgba(0, 255, 136, 0.3)', borderRadius: '0.375rem', padding: '0.75rem', cursor: 'pointer', transition: 'all 0.2s' }} className="hover:border-intel-success">
<h3 className="text-white font-semibold text-sm mb-1 font-mono">Patching Policy</h3>
<p className="text-gray-400 text-xs mb-2">Enterprise patch management timelines and approval workflow...</p>
<span className="text-xs text-intel-success font-mono">Last updated: 2024-01-15</span>
</div>
<div style={{ background: 'linear-gradient(135deg, rgba(19, 25, 55, 0.85) 0%, rgba(30, 39, 73, 0.75) 100%)', border: '1px solid rgba(0, 255, 136, 0.3)', borderRadius: '0.375rem', padding: '0.75rem', cursor: 'pointer', transition: 'all 0.2s' }} className="hover:border-intel-success">
<h3 className="text-white font-semibold text-sm mb-1 font-mono">Documentation Standards</h3>
<p className="text-gray-400 text-xs mb-2">Required documentation for vulnerability tracking and audit compliance...</p>
<span className="text-xs text-intel-success font-mono">Last updated: 2024-01-10</span>
</div>
</div>
</div>
</div> </div>
{quickCheckResult && ( {/* CENTER PANEL - Main Content */}
<div className={`mt-4 p-4 rounded border ${quickCheckResult.exists ? 'bg-intel-success/10 border-intel-success/30' : 'bg-intel-warning/10 border-intel-warning/30'}`}> <div className="col-span-12 lg:col-span-6 space-y-4">
{quickCheckResult.error ? ( {/* Quick Check */}
<div className="flex items-start gap-3"> <div style={{...STYLES.intelCard, padding: '1.5rem'}} className="rounded-lg">
<XCircle className="w-5 h-5 text-intel-danger mt-0.5" /> <div className="scan-line"></div>
<div> <h2 style={{ fontSize: '1.125rem', fontWeight: '600', color: '#00D9FF', marginBottom: '0.75rem', fontFamily: 'monospace', textTransform: 'uppercase', letterSpacing: '0.1em', textShadow: '0 0 20px rgba(0, 217, 255, 0.5)' }}>Quick CVE Lookup</h2>
<p className="font-medium text-intel-danger font-mono">Error</p> <div className="flex gap-3">
<p className="text-sm text-gray-300">{quickCheckResult.error}</p> <input
</div> type="text"
</div> placeholder="Enter CVE ID (e.g., CVE-2024-1234)"
) : quickCheckResult.exists ? ( value={quickCheckCVE}
<div className="flex items-start gap-3"> onChange={(e) => setQuickCheckCVE(e.target.value)}
<CheckCircle className="w-5 h-5 text-intel-success mt-0.5" /> onKeyPress={(e) => e.key === 'Enter' && quickCheckCVEStatus()}
<div className="flex-1"> className="flex-1 intel-input"
<p className="font-medium text-intel-success font-mono"> CVE Addressed ({quickCheckResult.vendors.length} vendor{quickCheckResult.vendors.length > 1 ? 's' : ''})</p> />
<div className="mt-3 space-y-3">
{quickCheckResult.vendors.map((vendorInfo, idx) => (
<div key={idx} className="p-3 bg-intel-dark/70 rounded border border-intel-accent/30 shadow-lg">
<p className="font-semibold text-white mb-2 font-sans">{vendorInfo.vendor}</p>
<div className="grid grid-cols-2 gap-2 text-sm text-gray-300 mb-2 font-mono">
<p><strong className="text-white">Severity:</strong> {vendorInfo.severity}</p>
<p><strong className="text-white">Status:</strong> {vendorInfo.status}</p>
<p><strong className="text-white">Documents:</strong> {vendorInfo.total_documents} attached</p>
</div>
</div>
))}
</div>
</div>
</div>
) : (
<div className="flex items-start gap-3">
<AlertCircle className="w-5 h-5 text-intel-warning mt-0.5" />
<div>
<p className="font-medium text-intel-warning font-mono">Not Found</p>
<p className="text-sm text-gray-300">This CVE has not been addressed yet. No entry exists in the database.</p>
</div>
</div>
)}
</div>
)}
</div>
{/* Open Vendor Tickets Dashboard */}
{jiraTickets.filter(t => t.status !== 'Closed').length > 0 && (
<div style={{...STYLES.intelCard, padding: '1.5rem', marginBottom: '1.5rem', borderLeft: '4px solid #FFB800'}} className="rounded-lg">
<div className="flex justify-between items-center mb-4">
<h2 style={{ fontSize: '1.125rem', fontWeight: '600', color: '#FFB800', display: 'flex', alignItems: 'center', gap: '0.5rem', fontFamily: 'monospace', textTransform: 'uppercase', letterSpacing: '0.1em', textShadow: '0 0 15px rgba(255, 184, 0, 0.5)' }}>
<AlertCircle className="w-5 h-5" />
Open Tickets ({jiraTickets.filter(t => t.status !== 'Closed').length})
</h2>
{canWrite() && (
<button <button
onClick={() => { setAddTicketContext(null); setTicketForm({ cve_id: '', vendor: '', ticket_key: '', url: '', summary: '', status: 'Open' }); setShowAddTicket(true); }} onClick={quickCheckCVEStatus}
className="intel-button intel-button-primary flex items-center gap-1" className="intel-button intel-button-primary"
> >
<Plus className="w-4 h-4" /> Scan
Add
</button> </button>
)} </div>
</div>
<div className="space-y-2"> {quickCheckResult && (
{jiraTickets.filter(t => t.status !== 'Closed').map(ticket => ( <div className={`mt-4 p-4 rounded border ${quickCheckResult.exists ? 'bg-intel-success/10 border-intel-success/30' : 'bg-intel-warning/10 border-intel-warning/30'}`}>
<div key={ticket.id} style={{ background: 'linear-gradient(135deg, rgba(19, 25, 55, 0.85) 0%, rgba(30, 39, 73, 0.75) 100%)', border: '1px solid rgba(255, 184, 0, 0.3)', borderRadius: '0.375rem', padding: '0.75rem', boxShadow: '0 2px 6px rgba(0, 0, 0, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.04)' }} className="flex items-center justify-between"> {quickCheckResult.error ? (
<div className="flex items-center gap-4 flex-1"> <div className="flex items-start gap-3">
<a <XCircle className="w-5 h-5 text-intel-danger mt-0.5" />
href={ticket.url || '#'} <div>
target="_blank" <p className="font-medium text-intel-danger font-mono">Error</p>
rel="noopener noreferrer" <p className="text-sm text-gray-300">{quickCheckResult.error}</p>
className="font-mono text-sm font-semibold text-intel-accent hover:text-intel-warning transition-colors" </div>
> </div>
{ticket.ticket_key} ) : quickCheckResult.exists ? (
</a> <div className="flex items-start gap-3">
<span className="text-sm text-white font-mono">{ticket.cve_id}</span> <CheckCircle className="w-5 h-5 text-intel-success mt-0.5" />
<span style={{ fontSize: '0.875rem', color: '#E4E8F1', fontFamily: 'monospace' }}>({ticket.vendor})</span> <div className="flex-1">
{ticket.summary && <span style={{ fontSize: '0.875rem', color: '#E4E8F1', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: '20rem' }}>{ticket.summary}</span>} <p className="font-medium text-intel-success font-mono"> CVE Addressed ({quickCheckResult.vendors.length} vendor{quickCheckResult.vendors.length > 1 ? 's' : ''})</p>
<span style={ticket.status === 'Open' ? STYLES.badgeCritical : STYLES.badgeHigh}> <div className="mt-3 space-y-3">
<span style={STYLES.glowDot(ticket.status === 'Open' ? '#FF3366' : '#FFB800')}></span> {quickCheckResult.vendors.map((vendorInfo, idx) => (
{ticket.status} <div key={idx} className="p-3 bg-intel-dark/70 rounded border border-intel-accent/30 shadow-lg">
</span> <p className="font-semibold text-white mb-2 font-sans">{vendorInfo.vendor}</p>
</div> <div className="grid grid-cols-2 gap-2 text-sm text-gray-300 mb-2 font-mono">
{canWrite() && ( <p><strong className="text-white">Severity:</strong> {vendorInfo.severity}</p>
<div className="flex gap-2"> <p><strong className="text-white">Status:</strong> {vendorInfo.status}</p>
<button onClick={() => handleEditTicket(ticket)} className="text-gray-400 hover:text-intel-warning transition-colors"> <p><strong className="text-white">Documents:</strong> {vendorInfo.total_documents} attached</p>
<Edit2 className="w-4 h-4" /> </div>
</button> </div>
<button onClick={() => handleDeleteTicket(ticket)} className="text-gray-400 hover:text-intel-danger transition-colors"> ))}
<Trash2 className="w-4 h-4" /> </div>
</button> </div>
</div>
) : (
<div className="flex items-start gap-3">
<AlertCircle className="w-5 h-5 text-intel-warning mt-0.5" />
<div>
<p className="font-medium text-intel-warning font-mono">Not Found</p>
<p className="text-sm text-gray-300">This CVE has not been addressed yet. No entry exists in the database.</p>
</div>
</div> </div>
)} )}
</div> </div>
))} )}
</div>
</div>
)}
{/* Search and Filters */}
<div style={{...STYLES.intelCard, padding: '1.5rem', marginBottom: '1.5rem'}} className="rounded-lg">
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div className="md:col-span-1">
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">
<Search className="inline w-4 h-4 mr-1" />
Search CVEs
</label>
<input
type="text"
placeholder="CVE ID or description..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="intel-input w-full"
/>
</div> </div>
<div> {/* Search and Filters */}
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider"> <div style={{...STYLES.intelCard, padding: '1.5rem'}} className="rounded-lg">
<Filter className="inline w-4 h-4 mr-1" /> <div className="grid grid-cols-1 gap-4">
Vendor <div>
</label> <label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">
<select <Search className="inline w-4 h-4 mr-1" />
value={selectedVendor} Search CVEs
onChange={(e) => setSelectedVendor(e.target.value)} </label>
className="intel-input w-full" <input
> type="text"
{vendors.map(vendor => ( placeholder="CVE ID or description..."
<option key={vendor} value={vendor}>{vendor}</option> value={searchQuery}
))} onChange={(e) => setSearchQuery(e.target.value)}
</select> className="intel-input w-full"
/>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">
<Filter className="inline w-4 h-4 mr-1" />
Vendor
</label>
<select
value={selectedVendor}
onChange={(e) => setSelectedVendor(e.target.value)}
className="intel-input w-full"
>
{vendors.map(vendor => (
<option key={vendor} value={vendor}>{vendor}</option>
))}
</select>
</div>
<div>
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">
<AlertCircle className="inline w-4 h-4 mr-1" />
Severity
</label>
<select
value={selectedSeverity}
onChange={(e) => setSelectedSeverity(e.target.value)}
className="intel-input w-full"
>
{severityLevels.map(level => (
<option key={level} value={level}>{level}</option>
))}
</select>
</div>
</div>
</div>
</div> </div>
<div> {/* Results Summary */}
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider"> <div className="flex justify-between items-center">
<AlertCircle className="inline w-4 h-4 mr-1" /> <p className="text-gray-400 font-mono text-sm">
Severity <span className="text-intel-accent font-bold">{Object.keys(filteredGroupedCVEs).length}</span> CVE{Object.keys(filteredGroupedCVEs).length !== 1 ? 's' : ''}
</label> <span className="text-gray-500 mx-2"></span>
<select <span className="text-gray-300">{cves.length}</span> vendor entr{cves.length !== 1 ? 'ies' : 'y'}
value={selectedSeverity} </p>
onChange={(e) => setSelectedSeverity(e.target.value)} {selectedDocuments.length > 0 && (
className="intel-input w-full" <button
> onClick={exportSelectedDocuments}
{severityLevels.map(level => ( className="intel-button intel-button-primary flex items-center gap-2"
<option key={level} value={level}>{level}</option> >
))} <Download className="w-4 h-4" />
</select> Export {selectedDocuments.length} Doc{selectedDocuments.length !== 1 ? 's' : ''}
</button>
)}
</div> </div>
</div>
</div>
{/* Results Summary */} {/* CVE List - Grouped by CVE ID */}
<div className="mb-4 flex justify-between items-center"> {loading ? (
<p className="text-gray-400 font-mono text-sm"> <div className="intel-card rounded-lg p-12 text-center">
<span className="text-intel-accent font-bold">{Object.keys(filteredGroupedCVEs).length}</span> CVE{Object.keys(filteredGroupedCVEs).length !== 1 ? 's' : ''} <div className="loading-spinner w-12 h-12 mx-auto mb-4"></div>
<span className="text-gray-500 mx-2"></span> <p className="text-gray-400 font-mono text-sm uppercase tracking-wider">Scanning Vulnerabilities...</p>
<span className="text-gray-300">{cves.length}</span> vendor entr{cves.length !== 1 ? 'ies' : 'y'} </div>
</p> ) : error ? (
{selectedDocuments.length > 0 && ( <div className="intel-card rounded-lg p-12 text-center border-intel-danger">
<button <XCircle className="w-12 h-12 text-intel-danger mx-auto mb-4" />
onClick={exportSelectedDocuments} <h3 className="text-lg font-medium text-gray-200 mb-2 font-mono">Error Loading CVEs</h3>
className="intel-button intel-button-primary flex items-center gap-2" <p className="text-gray-400 mb-4">{error}</p>
> <button
<Download className="w-4 h-4" /> onClick={fetchCVEs}
Export {selectedDocuments.length} Doc{selectedDocuments.length !== 1 ? 's' : ''} className="intel-button intel-button-primary"
</button> >
)} Retry
</div> </button>
</div>
{/* CVE List - Grouped by CVE ID */} ) : (
{loading ? ( <div className="space-y-4">
<div className="intel-card rounded-lg p-12 text-center">
<div className="loading-spinner w-12 h-12 mx-auto mb-4"></div>
<p className="text-gray-400 font-mono text-sm uppercase tracking-wider">Scanning Vulnerabilities...</p>
</div>
) : error ? (
<div className="intel-card rounded-lg p-12 text-center border-intel-danger">
<XCircle className="w-12 h-12 text-intel-danger mx-auto mb-4" />
<h3 className="text-lg font-medium text-gray-200 mb-2 font-mono">Error Loading CVEs</h3>
<p className="text-gray-400 mb-4">{error}</p>
<button
onClick={fetchCVEs}
className="intel-button intel-button-primary"
>
Retry
</button>
</div>
) : (
<div className="space-y-4">
{Object.entries(filteredGroupedCVEs).map(([cveId, vendorEntries]) => { {Object.entries(filteredGroupedCVEs).map(([cveId, vendorEntries]) => {
const isCVEExpanded = expandedCVEs[cveId]; const isCVEExpanded = expandedCVEs[cveId];
const severityOrder = { 'Critical': 0, 'High': 1, 'Medium': 2, 'Low': 3 }; const severityOrder = { 'Critical': 0, 'High': 1, 'Medium': 2, 'Low': 3 };
@@ -1733,16 +1727,155 @@ export default function App() {
</div> </div>
); );
})} })}
</div> </div>
)} )}
{Object.keys(filteredGroupedCVEs).length === 0 && !loading && ( {Object.keys(filteredGroupedCVEs).length === 0 && !loading && (
<div className="intel-card rounded-lg p-12 text-center"> <div className="intel-card rounded-lg p-12 text-center">
<AlertCircle className="w-12 h-12 text-gray-400 mx-auto mb-4" /> <AlertCircle className="w-12 h-12 text-gray-400 mx-auto mb-4" />
<h3 className="text-lg font-medium text-white mb-2 font-mono">No CVEs Found</h3> <h3 className="text-lg font-medium text-white mb-2 font-mono">No CVEs Found</h3>
<p className="text-gray-300">Try adjusting your search criteria or filters</p> <p className="text-gray-300">Try adjusting your search criteria or filters</p>
</div>
)}
</div> </div>
)} {/* End Center Panel */}
{/* RIGHT PANEL - Calendar & Open Tickets */}
<div className="col-span-12 lg:col-span-3 space-y-4">
{/* Calendar Widget */}
<div style={{...STYLES.intelCard, padding: '1.5rem', borderLeft: '4px solid #00D9FF'}} className="rounded-lg">
<h2 style={{ fontSize: '1.125rem', fontWeight: '600', color: '#00D9FF', marginBottom: '1rem', fontFamily: 'monospace', textTransform: 'uppercase', letterSpacing: '0.1em', textShadow: '0 0 15px rgba(0, 217, 255, 0.5)' }}>
Calendar
</h2>
{/* Simple Calendar Grid */}
<div className="mb-2">
<div className="text-center mb-3">
<span className="text-white font-semibold font-mono">February 2024</span>
</div>
<div className="grid grid-cols-7 gap-1 text-center text-xs mb-2">
<div className="text-gray-400 font-mono">Su</div>
<div className="text-gray-400 font-mono">Mo</div>
<div className="text-gray-400 font-mono">Tu</div>
<div className="text-gray-400 font-mono">We</div>
<div className="text-gray-400 font-mono">Th</div>
<div className="text-gray-400 font-mono">Fr</div>
<div className="text-gray-400 font-mono">Sa</div>
</div>
<div className="grid grid-cols-7 gap-1 text-center">
{/* Week 1 */}
<div className="text-gray-600 font-mono text-xs p-1">28</div>
<div className="text-gray-600 font-mono text-xs p-1">29</div>
<div className="text-gray-600 font-mono text-xs p-1">30</div>
<div className="text-gray-600 font-mono text-xs p-1">31</div>
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">1</div>
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">2</div>
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">3</div>
{/* Week 2 */}
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">4</div>
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">5</div>
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">6</div>
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">7</div>
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">8</div>
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">9</div>
<div className="bg-intel-accent/30 text-white font-mono text-xs p-1 rounded font-bold border border-intel-accent">10</div>
{/* Week 3 */}
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">11</div>
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">12</div>
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">13</div>
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">14</div>
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">15</div>
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">16</div>
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">17</div>
{/* Week 4 */}
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">18</div>
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">19</div>
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">20</div>
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">21</div>
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">22</div>
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">23</div>
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">24</div>
{/* Week 5 */}
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">25</div>
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">26</div>
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">27</div>
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">28</div>
<div className="text-white font-mono text-xs p-1 hover:bg-intel-accent/20 rounded cursor-pointer">29</div>
<div className="text-gray-600 font-mono text-xs p-1">1</div>
<div className="text-gray-600 font-mono text-xs p-1">2</div>
</div>
</div>
</div>
{/* Open Vendor Tickets */}
<div style={{...STYLES.intelCard, padding: '1.5rem', borderLeft: '4px solid #FFB800'}} className="rounded-lg">
<div className="flex justify-between items-center mb-4">
<h2 style={{ fontSize: '1.125rem', fontWeight: '600', color: '#FFB800', display: 'flex', alignItems: 'center', gap: '0.5rem', fontFamily: 'monospace', textTransform: 'uppercase', letterSpacing: '0.1em', textShadow: '0 0 15px rgba(255, 184, 0, 0.5)' }}>
<AlertCircle className="w-5 h-5" />
Open Tickets
</h2>
{canWrite() && (
<button
onClick={() => { setAddTicketContext(null); setTicketForm({ cve_id: '', vendor: '', ticket_key: '', url: '', summary: '', status: 'Open' }); setShowAddTicket(true); }}
className="intel-button intel-button-primary flex items-center gap-1 text-xs px-2 py-1"
>
<Plus className="w-3 h-3" />
</button>
)}
</div>
<div className="text-center mb-3">
<div style={{ fontSize: '2rem', fontWeight: '700', fontFamily: 'monospace', color: '#FFB800', textShadow: '0 0 20px rgba(255, 184, 0, 0.5)' }}>
{jiraTickets.filter(t => t.status !== 'Closed').length}
</div>
<div className="text-xs text-gray-400 uppercase tracking-wider">Active</div>
</div>
<div className="space-y-2 max-h-96 overflow-y-auto">
{jiraTickets.filter(t => t.status !== 'Closed').slice(0, 10).map(ticket => (
<div key={ticket.id} style={{ background: 'linear-gradient(135deg, rgba(19, 25, 55, 0.85) 0%, rgba(30, 39, 73, 0.75) 100%)', border: '1px solid rgba(255, 184, 0, 0.3)', borderRadius: '0.375rem', padding: '0.5rem', boxShadow: '0 2px 6px rgba(0, 0, 0, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.04)' }}>
<div className="flex items-start justify-between gap-2 mb-1">
<a
href={ticket.url || '#'}
target="_blank"
rel="noopener noreferrer"
className="font-mono text-xs font-semibold text-intel-accent hover:text-intel-warning transition-colors"
>
{ticket.ticket_key}
</a>
{canWrite() && (
<div className="flex gap-1">
<button onClick={() => handleEditTicket(ticket)} className="text-gray-400 hover:text-intel-warning transition-colors">
<Edit2 className="w-3 h-3" />
</button>
<button onClick={() => handleDeleteTicket(ticket)} className="text-gray-400 hover:text-intel-danger transition-colors">
<Trash2 className="w-3 h-3" />
</button>
</div>
)}
</div>
<div className="text-xs text-white font-mono mb-1">{ticket.cve_id}</div>
<div className="text-xs text-gray-400">{ticket.vendor}</div>
{ticket.summary && <div className="text-xs text-gray-300 mt-1 truncate">{ticket.summary}</div>}
<div className="mt-2">
<span style={{ ...STYLES.badgeHigh, fontSize: '0.65rem', padding: '0.25rem 0.5rem' }}>
<span style={{...STYLES.glowDot('#FFB800'), width: '6px', height: '6px'}}></span>
{ticket.status}
</span>
</div>
</div>
))}
{jiraTickets.filter(t => t.status !== 'Closed').length === 0 && (
<div className="text-center py-8">
<CheckCircle className="w-8 h-8 text-intel-success mx-auto mb-2" />
<p className="text-sm text-gray-400 italic font-mono">No open tickets</p>
</div>
)}
</div>
</div>
</div>
{/* End Right Panel */}
</div>
{/* End Three Column Layout */}
</div> </div>
</div> </div>
); );