Deploy on 2026-06-05 16:42:14

This commit is contained in:
Hamza-Ayed
2026-06-05 16:42:14 +03:00
parent 54065628bf
commit 89b72a0b42
5 changed files with 206 additions and 8 deletions

View File

@@ -83,6 +83,13 @@ return [
'interactions_logged' => 'التفاعلات المسجلة',
'today_contacts' => 'جهات اتصال مضافة اليوم',
'today_orgs' => 'منظمات جديدة',
'telegram_chat_id_hint' => 'ملاحظة: إذا كنت ترسل إلى قناة أو مجموعة تيليجرام، يجب إضافة البوت كمسؤول (Administrator) وتفعيل صلاحية نشر الرسائل.',
'recent_activities' => 'آخر النشاطات',
'recent_opportunities' => 'آخر الفرص',
'platform_intro_title' => 'ScoutIQ - الاستكشاف الذكي للمستثمرين بالذكاء الاصطناعي',
'platform_intro_desc' => 'عبارة عن منصة استخبارات مؤتمتة مصممة لاكتشاف وتتبع وتقييم الشركات الناشئة في المراحل المبكرة وصناديق الاستثمار الجريء والمسرعات. يقوم النظام بجمع البيانات من المصادر، وتحليلها باستخدام الذكاء الاصطناعي (Gemini)، وتحديث خط أنابيب CRM الخاص بك.',
'desc_organizations' => 'تتبع صناديق الاستثمار الجريء، ومجموعات المسرعات، وملفات المستثمرين الملائكيين مع بيانات وصفية عميقة.',
'desc_opportunities' => 'البرامج الاستثمارية، ومنح التمويل، والمسابقات، وفعاليات الشركات الناشئة المكتشفة بواسطة الذكاء الاصطناعي.',
'desc_crm' => 'إدارة ملفات تعريف جهات الاتصال، وجدولة الاجتماعات، وتسجيل تفاعلات البريد الإلكتروني، وتتبع الصفقات.',
'desc_sources' => 'تكوين خلاصات RSS ومصادر واجهة برمجة التطبيقات (API) لمسح الأنظمة البيئية تلقائيًا بحثًا عن الإشارات المبكرة.',
];

View File

@@ -83,6 +83,13 @@ return [
'interactions_logged' => 'Interactions Logged',
'today_contacts' => 'Contacts Added Today',
'today_orgs' => 'new organizations',
'telegram_chat_id_hint' => 'Note: If sending to a Telegram channel or group, you must add the bot as an Administrator with message post permissions.',
'recent_activities' => 'Recent Activities',
'recent_opportunities' => 'Recent Opportunities',
'platform_intro_title' => 'ScoutIQ - AI-Powered Investor Intelligence',
'platform_intro_desc' => 'ScoutIQ is an automated intelligence platform designed to discover, track, and score early-stage startups, venture capital funds, and accelerators. The system collects data from feeds, analyzes them using Gemini AI, and updates your CRM pipeline.',
'desc_organizations' => 'Track VC funds, accelerator cohorts, and angel investor profiles with deep metadata.',
'desc_opportunities' => 'AI-discovered investment programs, funding grants, competitions, and startup events.',
'desc_crm' => 'Manage contact profiles, schedule meetings, log email interactions, and track deals.',
'desc_sources' => 'Configure RSS and API feeds to automatically scan ecosystems for early signals.',
];

View File

@@ -8,8 +8,38 @@
</div>
</div>
<!-- Onboarding / Platform Overview Panel -->
<div class="glass-panel onboarding-card" style="padding: 28px; margin-top: 24px; position: relative; overflow: hidden;">
<div style="position: absolute; top: -50px; right: -50px; width: 200px; height: 200px; background: radial-gradient(circle, var(--accent-glow) 0%, transparent 70%); pointer-events: none;"></div>
<h2 style="font-size: 1.4rem; font-weight: 700; margin-bottom: 12px; display: flex; align-items: center; gap: 10px; color: var(--text-main);">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" style="color: var(--accent);"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line></svg>
<?= $t['platform_intro_title'] ?? 'ScoutIQ - AI-Powered Investor Intelligence' ?>
</h2>
<p style="color: var(--text-muted); line-height: 1.6; font-size: 0.95rem; margin-bottom: 16px;">
<?= $t['platform_intro_desc'] ?? 'ScoutIQ is an automated intelligence platform designed to discover, track, and score investment opportunities, early-stage startups, and venture funds. The system crawls configured data feeds, processes them using Gemini AI, and routes them to your CRM pipeline.' ?>
</p>
<div class="onboarding-steps" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px;">
<div style="background: rgba(255,255,255,0.02); padding: 16px; border-radius: var(--radius-md); border: 1px solid rgba(255,255,255,0.03);">
<h4 style="color: var(--accent); margin-bottom: 6px; font-size: 0.95rem; font-weight: 600;"><?= $t['organizations'] ?? 'Organizations' ?></h4>
<span style="font-size: 0.85rem; color: var(--text-muted);"><?= $t['desc_organizations'] ?? 'Track VC funds, accelerator cohorts, and angel investor profiles with deep metadata.' ?></span>
</div>
<div style="background: rgba(255,255,255,0.02); padding: 16px; border-radius: var(--radius-md); border: 1px solid rgba(255,255,255,0.03);">
<h4 style="color: var(--accent); margin-bottom: 6px; font-size: 0.95rem; font-weight: 600;"><?= $t['opportunities'] ?? 'Opportunities' ?></h4>
<span style="font-size: 0.85rem; color: var(--text-muted);"><?= $t['desc_opportunities'] ?? 'AI-discovered investment programs, funding grants, competitions, and startup events.' ?></span>
</div>
<div style="background: rgba(255,255,255,0.02); padding: 16px; border-radius: var(--radius-md); border: 1px solid rgba(255,255,255,0.03);">
<h4 style="color: var(--accent); margin-bottom: 6px; font-size: 0.95rem; font-weight: 600;"><?= $t['crm_status'] ?? 'CRM Pipeline' ?></h4>
<span style="font-size: 0.85rem; color: var(--text-muted);"><?= $t['desc_crm'] ?? 'Manage contact profiles, schedule meetings, log email interactions, and track deals.' ?></span>
</div>
<div style="background: rgba(255,255,255,0.02); padding: 16px; border-radius: var(--radius-md); border: 1px solid rgba(255,255,255,0.03);">
<h4 style="color: var(--accent); margin-bottom: 6px; font-size: 0.95rem; font-weight: 600;"><?= $t['sources'] ?? 'Data Sources' ?></h4>
<span style="font-size: 0.85rem; color: var(--text-muted);"><?= $t['desc_sources'] ?? 'Configure RSS and API feeds to automatically scan ecosystems for early signals.' ?></span>
</div>
</div>
</div>
<!-- Metrics Row -->
<div class="metrics-grid">
<div class="metrics-grid" style="margin-top: 24px;">
<div class="glass-panel metric-card">
<span class="metric-title"><?= $t['total_organizations'] ?? 'Organizations' ?></span>
<span class="metric-value"><?= $stats['organizations'] ?></span>
@@ -47,7 +77,24 @@
</div>
</div>
<div class="charts-grid">
<!-- Charts Row -->
<div class="charts-grid" style="margin-top: 24px;">
<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>
</div>
<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>
</div>
</div>
<div class="charts-grid" style="margin-top: 24px;">
<!-- Recent Opportunities -->
<div class="glass-panel chart-card">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;">
@@ -64,7 +111,7 @@
<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 class="badge badge-type"><?= $this->escape($opp['type']) ?></span>
<span style="font-size: 0.8rem; color: var(--text-muted);">Score: <?= $opp['score'] ?></span>
</div>
</div>
@@ -104,4 +151,125 @@
<style>
.list-item { padding: 12px 0; border-bottom: 1px solid rgba(255,255,255,0.05); }
.list-item:last-child { border-bottom: none; }
.badge-type { background: rgba(255, 255, 255, 0.05); color: var(--text-muted); font-size: 0.8rem; padding: 4px 8px; border-radius: 4px; text-transform: capitalize; }
/* RTL adjustments */
html[dir="rtl"] .list-item { text-align: right; }
html[dir="rtl"] .onboarding-card { text-align: right; }
html[dir="rtl"] .onboarding-steps { text-align: right; }
</style>
<script>
// Category Chart (Doughnut)
const ctxCategory = document.getElementById('categoryChart').getContext('2d');
const categoriesData = <?= json_encode($opportunities_by_type ?? []) ?>;
const hasCategoryData = Object.keys(categoriesData).length > 0;
const categoryLabels = hasCategoryData
? Object.keys(categoriesData).map(k => {
const trans = {
'grant': '<?= $t['grant'] ?? 'Grants' ?>',
'competition': '<?= $t['competition'] ?? 'Competitions' ?>',
'demo_day': '<?= $t['demo_day'] ?? 'Demo Days' ?>',
'event': '<?= $t['event'] ?? 'Events' ?>',
'partnership': '<?= $t['partnership'] ?? 'Partnerships' ?>',
'investment': '<?= $t['investment'] ?? 'Investments' ?>',
'other': '<?= $t['other'] ?? 'Other' ?>'
};
return trans[k] || k.charAt(0).toUpperCase() + k.slice(1);
})
: ['Mobility & Logistics', 'AI & Automation', 'SaaS', 'Fintech', 'Marketplaces'];
const categoryValues = hasCategoryData
? Object.values(categoriesData)
: [35, 25, 20, 12, 8];
new Chart(ctxCategory, {
type: 'doughnut',
data: {
labels: categoryLabels,
datasets: [{
data: categoryValues,
backgroundColor: [
'hsl(263, 90%, 60%)',
'hsl(220, 95%, 50%)',
'hsl(180, 100%, 40%)',
'hsl(142, 70%, 45%)',
'hsl(38, 92%, 50%)',
'hsl(330, 90%, 60%)',
'hsl(20, 90%, 60%)'
],
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');
const growthOpps = <?= json_encode($growth_opportunities ?? []) ?>;
const growthInters = <?= json_encode($growth_interactions ?? []) ?>;
const hasGrowthData = (growthOpps.reduce((a, b) => a + b, 0) + growthInters.reduce((a, b) => a + b, 0)) > 0;
const growthLabels = <?= json_encode($growth_labels ?? ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun']) ?>;
const growthOppsData = hasGrowthData ? growthOpps : [12, 19, 32, 45, 68, 96];
const growthIntersData = hasGrowthData ? growthInters : [5, 12, 18, 25, 30, 48];
new Chart(ctxGrowth, {
type: 'line',
data: {
labels: growthLabels,
datasets: [{
label: '<?= $t['ingested_opportunities'] ?? 'Ingested Opportunities' ?>',
data: growthOppsData,
borderColor: 'hsl(180, 100%, 50%)',
backgroundColor: 'rgba(0, 242, 254, 0.1)',
borderWidth: 3,
fill: true,
tension: 0.4
}, {
label: '<?= $t['interactions_logged'] ?? 'Interactions Logged' ?>',
data: growthIntersData,
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>

View File

@@ -26,6 +26,9 @@
<div class="form-group">
<label class="form-label"><?= $t['telegram_chat_id'] ?? 'Chat ID' ?></label>
<input type="text" name="telegram_chat_id" class="form-control" value="<?= $this->escape($tg_chat_id) ?>" placeholder="-1001234567890">
<small style="color: var(--text-muted); font-size: 0.8rem; margin-top: 4px; display: block;">
<?= $t['telegram_chat_id_hint'] ?? 'Note: For Telegram channels/groups, you must add the bot as an Administrator with post permissions.' ?>
</small>
</div>
<div class="form-group" style="display: flex; align-items: center; gap: 10px;">
<label class="form-label" style="margin: 0;"><?= $t['telegram_enabled'] ?? 'Enable' ?></label>

View File

@@ -7,16 +7,29 @@
<link rel="stylesheet" href="/assets/css/app.css">
<link rel="stylesheet" href="/assets/css/admin.css">
<?php if (($lang ?? 'en') === 'ar'): ?>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.rtl.min.css">
<style>
.sidebar { border-right: none; border-left: 1px solid rgba(255,255,255,0.05); }
.nav-menu { padding-right: 0; }
.nav-item a svg { margin-right: 0; margin-left: 12px; }
.top-bar { flex-direction: row-reverse; }
body { font-family: 'Tajawal', 'Inter', sans-serif; }
.sidebar { border-right: none; border-left: 1px solid var(--border-color); }
.sidebar .brand { flex-direction: row-reverse; }
.nav-menu { padding-right: 0; }
.nav-item a { flex-direction: row-reverse; text-align: right; }
.nav-item a svg { margin-right: 0; margin-left: 14px; }
.top-bar { flex-direction: row-reverse; }
.user-info { flex-direction: row-reverse; }
.dashboard-header { text-align: right; }
.metric-card { text-align: right; }
.metric-card::before { left: auto; right: 0; }
.metric-footer { flex-direction: row-reverse; }
.chart-card { text-align: right; }
.data-table th, .data-table td { text-align: right; }
.form-group { text-align: right; }
.form-label { text-align: right; }
.btn { flex-direction: row-reverse; gap: 8px; }
.alert { text-align: right; flex-direction: row-reverse; }
.page-header { flex-direction: row-reverse; text-align: right; }
.detail-row { flex-direction: row-reverse; }
.detail-row span:first-child { text-align: right; }
.form-control { text-align: right; }
</style>
<?php endif; ?>
<link href="https://fonts.googleapis.com/css2?family=Tajawal:wght@400;500;700;800&display=swap" rel="stylesheet">