|
|
|
|
@@ -1,143 +1,107 @@
|
|
|
|
|
<div class="dashboard-header">
|
|
|
|
|
<h1>Welcome, <?= $this->escape($user['name']) ?></h1>
|
|
|
|
|
<p>Here is your daily intelligence summary for ScoutIQ.</p>
|
|
|
|
|
<div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap;">
|
|
|
|
|
<div>
|
|
|
|
|
<h1><?= $t['dashboard'] ?? 'Dashboard' ?></h1>
|
|
|
|
|
<p><?= $t['welcome'] ?? 'Welcome' ?>, <?= $this->escape($user['name']) ?></p>
|
|
|
|
|
</div>
|
|
|
|
|
<a href="/admin/sources" class="btn btn-primary"><?= $t['run_collector'] ?? 'Run Collector' ?></a>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Metrics Row -->
|
|
|
|
|
<div class="metrics-grid">
|
|
|
|
|
<div class="glass-panel metric-card">
|
|
|
|
|
<span class="metric-title">Total Investors</span>
|
|
|
|
|
<span class="metric-value">142</span>
|
|
|
|
|
<span class="metric-title"><?= $t['total_organizations'] ?? 'Organizations' ?></span>
|
|
|
|
|
<span class="metric-value"><?= $stats['organizations'] ?></span>
|
|
|
|
|
<span class="metric-footer">
|
|
|
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="23 6 13.5 15.5 8.5 10.5 1 18"></polyline><polyline points="17 6 23 6 23 12"></polyline></svg>
|
|
|
|
|
<span>+12% vs last month</span>
|
|
|
|
|
<span><?= $stats['vc'] ?> VC • <?= $stats['accelerators'] ?> Accelerators</span>
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="glass-panel metric-card">
|
|
|
|
|
<span class="metric-title">Total Accelerators</span>
|
|
|
|
|
<span class="metric-value">38</span>
|
|
|
|
|
<span class="metric-title"><?= $t['total_opportunities'] ?? 'Opportunities' ?></span>
|
|
|
|
|
<span class="metric-value"><?= $stats['opportunities'] ?></span>
|
|
|
|
|
<span class="metric-footer">
|
|
|
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="23 6 13.5 15.5 8.5 10.5 1 18"></polyline><polyline points="17 6 23 6 23 12"></polyline></svg>
|
|
|
|
|
<span>+5% vs last month</span>
|
|
|
|
|
<span><?= $stats['today'] ?> new today</span>
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="glass-panel metric-card">
|
|
|
|
|
<span class="metric-title">Open Opportunities</span>
|
|
|
|
|
<span class="metric-value">29</span>
|
|
|
|
|
<span class="metric-footer" style="color: var(--warning);">
|
|
|
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
|
|
|
|
|
<span>4 closing this week</span>
|
|
|
|
|
<span class="metric-title"><?= $t['total_contacts'] ?? 'Contacts' ?></span>
|
|
|
|
|
<span class="metric-value"><?= $stats['contacts'] ?></span>
|
|
|
|
|
<span class="metric-footer">
|
|
|
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="23 6 13.5 15.5 8.5 10.5 1 18"></polyline><polyline points="17 6 23 6 23 12"></polyline></svg>
|
|
|
|
|
<span><?= $t['view_all'] ?? 'View all' ?></span>
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="glass-panel metric-card">
|
|
|
|
|
<span class="metric-title">Contacts Added Today</span>
|
|
|
|
|
<span class="metric-value">7</span>
|
|
|
|
|
<span class="metric-title"><?= $t['active_sources'] ?? 'Sources' ?></span>
|
|
|
|
|
<span class="metric-value"><?= $stats['sources'] ?></span>
|
|
|
|
|
<span class="metric-footer">
|
|
|
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="23 6 13.5 15.5 8.5 10.5 1 18"></polyline><polyline points="17 6 23 6 23 12"></polyline></svg>
|
|
|
|
|
<span>+3 new organizations</span>
|
|
|
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline></svg>
|
|
|
|
|
<span>RSS feeds active</span>
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Charts Row -->
|
|
|
|
|
<div class="charts-grid">
|
|
|
|
|
<!-- Recent Opportunities -->
|
|
|
|
|
<div class="glass-panel chart-card">
|
|
|
|
|
<span class="chart-title">Opportunities by Category</span>
|
|
|
|
|
<div style="flex: 1; position: relative;">
|
|
|
|
|
<canvas id="categoryChart"></canvas>
|
|
|
|
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;">
|
|
|
|
|
<span class="chart-title"><?= $t['recent_opportunities'] ?? 'Recent Opportunities' ?></span>
|
|
|
|
|
<a href="/admin/opportunities" class="btn btn-sm btn-secondary"><?= $t['view_all'] ?? 'View All' ?></a>
|
|
|
|
|
</div>
|
|
|
|
|
<div style="max-height: 400px; overflow-y: auto;">
|
|
|
|
|
<?php if (empty($recent_opportunities)): ?>
|
|
|
|
|
<p style="color: var(--text-muted); text-align: center; padding: 40px;">No opportunities yet. Run the collector to start gathering data.</p>
|
|
|
|
|
<?php else: ?>
|
|
|
|
|
<?php foreach ($recent_opportunities as $opp): ?>
|
|
|
|
|
<div class="list-item">
|
|
|
|
|
<div style="display: flex; justify-content: space-between; gap: 10px;">
|
|
|
|
|
<div style="flex: 1; min-width: 0;">
|
|
|
|
|
<a href="/admin/opportunities/<?= $opp['id'] ?>" style="font-weight: 600;"><?= $this->escape(mb_substr($opp['title'], 0, 80)) ?></a>
|
|
|
|
|
<div style="display: flex; gap: 8px; margin-top: 4px; flex-wrap: wrap;">
|
|
|
|
|
<span class="badge badge-type-<?= $opp['type'] ?>"><?= $this->escape($opp['type']) ?></span>
|
|
|
|
|
<span style="font-size: 0.8rem; color: var(--text-muted);">Score: <?= $opp['score'] ?></span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<small style="color: var(--text-muted); white-space: nowrap;"><?= date('M j', strtotime($opp['created_at'])) ?></small>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<?php endforeach; ?>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Recent Activities -->
|
|
|
|
|
<div class="glass-panel chart-card">
|
|
|
|
|
<span class="chart-title">Monthly Growth & Ingestion</span>
|
|
|
|
|
<div style="flex: 1; position: relative;">
|
|
|
|
|
<canvas id="growthChart"></canvas>
|
|
|
|
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;">
|
|
|
|
|
<span class="chart-title"><?= $t['recent_activities'] ?? 'Recent Activity' ?></span>
|
|
|
|
|
</div>
|
|
|
|
|
<div style="max-height: 400px; overflow-y: auto;">
|
|
|
|
|
<?php if (empty($recent_activities)): ?>
|
|
|
|
|
<p style="color: var(--text-muted); text-align: center; padding: 40px;">No recent activity.</p>
|
|
|
|
|
<?php else: ?>
|
|
|
|
|
<?php foreach ($recent_activities as $activity): ?>
|
|
|
|
|
<div class="list-item">
|
|
|
|
|
<div style="display: flex; justify-content: space-between; gap: 10px;">
|
|
|
|
|
<div>
|
|
|
|
|
<span class="badge" style="background: rgba(139, 92, 246, 0.2); color: #a78bfa;"><?= $this->escape($activity['action'] ?? 'info') ?></span>
|
|
|
|
|
<span style="font-size: 0.85rem; color: var(--text-muted); margin-left: 8px;"><?= $this->escape(mb_substr($activity['description'] ?? '', 0, 100)) ?></span>
|
|
|
|
|
</div>
|
|
|
|
|
<small style="color: var(--text-muted); white-space: nowrap;"><?= date('M j, g:i a', strtotime($activity['created_at'])) ?></small>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<?php endforeach; ?>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
// Category Chart (Doughnut)
|
|
|
|
|
const ctxCategory = document.getElementById('categoryChart').getContext('2d');
|
|
|
|
|
new Chart(ctxCategory, {
|
|
|
|
|
type: 'doughnut',
|
|
|
|
|
data: {
|
|
|
|
|
labels: ['Mobility & Logistics', 'AI & Automation', 'SaaS', 'Fintech', 'Marketplaces'],
|
|
|
|
|
datasets: [{
|
|
|
|
|
data: [35, 25, 20, 12, 8],
|
|
|
|
|
backgroundColor: [
|
|
|
|
|
'hsl(263, 90%, 60%)',
|
|
|
|
|
'hsl(220, 95%, 50%)',
|
|
|
|
|
'hsl(180, 100%, 40%)',
|
|
|
|
|
'hsl(142, 70%, 45%)',
|
|
|
|
|
'hsl(38, 92%, 50%)'
|
|
|
|
|
],
|
|
|
|
|
borderWidth: 0
|
|
|
|
|
}]
|
|
|
|
|
},
|
|
|
|
|
options: {
|
|
|
|
|
responsive: true,
|
|
|
|
|
maintainAspectRatio: false,
|
|
|
|
|
plugins: {
|
|
|
|
|
legend: {
|
|
|
|
|
position: 'bottom',
|
|
|
|
|
labels: {
|
|
|
|
|
color: 'hsl(215, 20%, 75%)',
|
|
|
|
|
font: { family: 'Inter', size: 12 }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Growth Chart (Line)
|
|
|
|
|
const ctxGrowth = document.getElementById('growthChart').getContext('2d');
|
|
|
|
|
new Chart(ctxGrowth, {
|
|
|
|
|
type: 'line',
|
|
|
|
|
data: {
|
|
|
|
|
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
|
|
|
|
|
datasets: [{
|
|
|
|
|
label: 'Ingested Opportunities',
|
|
|
|
|
data: [12, 19, 32, 45, 68, 96],
|
|
|
|
|
borderColor: 'hsl(180, 100%, 50%)',
|
|
|
|
|
backgroundColor: 'rgba(0, 242, 254, 0.1)',
|
|
|
|
|
borderWidth: 3,
|
|
|
|
|
fill: true,
|
|
|
|
|
tension: 0.4
|
|
|
|
|
}, {
|
|
|
|
|
label: 'Interactions Logged',
|
|
|
|
|
data: [5, 12, 18, 25, 30, 48],
|
|
|
|
|
borderColor: 'hsl(263, 90%, 60%)',
|
|
|
|
|
backgroundColor: 'transparent',
|
|
|
|
|
borderWidth: 3,
|
|
|
|
|
tension: 0.4
|
|
|
|
|
}]
|
|
|
|
|
},
|
|
|
|
|
options: {
|
|
|
|
|
responsive: true,
|
|
|
|
|
maintainAspectRatio: false,
|
|
|
|
|
plugins: {
|
|
|
|
|
legend: {
|
|
|
|
|
position: 'bottom',
|
|
|
|
|
labels: {
|
|
|
|
|
color: 'hsl(215, 20%, 75%)',
|
|
|
|
|
font: { family: 'Inter', size: 12 }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
scales: {
|
|
|
|
|
x: {
|
|
|
|
|
grid: { color: 'rgba(255, 255, 255, 0.05)' },
|
|
|
|
|
ticks: { color: 'hsl(215, 20%, 70%)' }
|
|
|
|
|
},
|
|
|
|
|
y: {
|
|
|
|
|
grid: { color: 'rgba(255, 255, 255, 0.05)' },
|
|
|
|
|
ticks: { color: 'hsl(215, 20%, 70%)' }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
</script>
|
|
|
|
|
<style>
|
|
|
|
|
.list-item { padding: 12px 0; border-bottom: 1px solid rgba(255,255,255,0.05); }
|
|
|
|
|
.list-item:last-child { border-bottom: none; }
|
|
|
|
|
</style>
|
|
|
|
|
|