| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>SkillScape AI Vision</title> |
| <script src="https://cdn.tailwindcss.com"></script> |
| <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script> |
| <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> |
| <script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.globe.min.js"></script> |
| <script> |
| tailwind.config = { |
| theme: { |
| extend: { |
| colors: { |
| primary: '#6366f1', |
| secondary: '#8b5cf6', |
| dark: '#0f172a', |
| light: '#f8fafc' |
| } |
| } |
| } |
| } |
| </script> |
| <style> |
| .skill-card { |
| transition: all 0.3s ease; |
| transform-style: preserve-3d; |
| } |
| .skill-card:hover { |
| transform: translateY(-5px) scale(1.02); |
| box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); |
| } |
| .category-header { |
| background: linear-gradient(90deg, rgba(99,102,241,0.1) 0%, rgba(139,92,246,0.1) 100%); |
| } |
| .progress-bar { |
| transition: width 1s ease-in-out; |
| } |
| .domain-badge { |
| background: linear-gradient(45deg, #6366f1, #8b5cf6); |
| } |
| </style> |
| </head> |
| <body class="bg-gradient-to-br from-gray-50 to-gray-100 min-h-screen"> |
| |
| <nav class="bg-white shadow-sm sticky top-0 z-50"> |
| <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> |
| <div class="flex justify-between h-16"> |
| <div class="flex items-center"> |
| <div class="flex-shrink-0 flex items-center"> |
| <i data-feather="bar-chart-2" class="h-8 w-8 text-primary"></i> |
| <span class="ml-2 text-xl font-bold text-gray-900">SkillScape AI Vision</span> |
| </div> |
| </div> |
| <div class="flex items-center"> |
| <div class="flex space-x-4"> |
| <button id="yearToggle" class="px-4 py-2 rounded-lg bg-primary text-white font-medium">2025 Data</button> |
| <button id="domainToggle" class="px-4 py-2 rounded-lg bg-secondary text-white font-medium">AI Domain</button> |
| </div> |
| </div> |
| </div> |
| </div> |
| </nav> |
|
|
| |
| <div id="vanta-bg" class="relative h-64 md:h-80 flex items-center justify-center"> |
| <div class="absolute inset-0 bg-gradient-to-r from-primary/20 to-secondary/20 z-10"></div> |
| <div class="relative z-20 text-center px-4"> |
| <h1 class="text-3xl md:text-5xl font-bold text-white mb-4">AI Skills Evolution</h1> |
| <p class="text-xl text-white/90 max-w-3xl mx-auto">Visualizing the transformation of AI skills from 2019 to 2025</p> |
| </div> |
| </div> |
|
|
| |
| <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12"> |
| |
| <div class="mb-10 bg-white rounded-xl shadow-sm p-6"> |
| <div class="flex flex-col md:flex-row justify-between items-start md:items-center space-y-4 md:space-y-0"> |
| <h2 class="text-2xl font-bold text-gray-900">Skill Analysis Dashboard</h2> |
| <div class="flex flex-wrap gap-3"> |
| <select id="yearFilter" class="border border-gray-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-primary focus:border-transparent"> |
| <option value="all">All Years</option> |
| <option value="2019">2019</option> |
| <option value="2025">2025</option> |
| </select> |
| <select id="domainFilter" class="border border-gray-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-primary focus:border-transparent"> |
| <option value="all">All Domains</option> |
| <option value="AI">AI</option> |
| <option value="ML">ML</option> |
| </select> |
| <select id="categoryFilter" class="border border-gray-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-primary focus:border-transparent"> |
| <option value="all">All Categories</option> |
| </select> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-10"> |
| <div class="bg-white rounded-xl shadow-sm p-6 flex items-center"> |
| <div class="rounded-full bg-primary/10 p-3 mr-4"> |
| <i data-feather="trending-up" class="h-6 w-6 text-primary"></i> |
| </div> |
| <div> |
| <p class="text-gray-500 text-sm">Total Skills</p> |
| <p class="text-2xl font-bold text-gray-900" id="totalSkills">0</p> |
| </div> |
| </div> |
| <div class="bg-white rounded-xl shadow-sm p-6 flex items-center"> |
| <div class="rounded-full bg-secondary/10 p-3 mr-4"> |
| <i data-feather="bar-chart-2" class="h-6 w-6 text-secondary"></i> |
| </div> |
| <div> |
| <p class="text-gray-500 text-sm">Top Category</p> |
| <p class="text-2xl font-bold text-gray-900" id="topCategory">-</p> |
| </div> |
| </div> |
| <div class="bg-white rounded-xl shadow-sm p-6 flex items-center"> |
| <div class="rounded-full bg-green-500/10 p-3 mr-4"> |
| <i data-feather="activity" class="h-6 w-6 text-green-500"></i> |
| </div> |
| <div> |
| <p class="text-gray-500 text-sm">Growth Rate</p> |
| <p class="text-2xl font-bold text-gray-900" id="growthRate">0%</p> |
| </div> |
| </div> |
| <div class="bg-white rounded-xl shadow-sm p-6 flex items-center"> |
| <div class="rounded-full bg-amber-500/10 p-3 mr-4"> |
| <i data-feather="award" class="h-6 w-6 text-amber-500"></i> |
| </div> |
| <div> |
| <p class="text-gray-500 text-sm">Top Skill</p> |
| <p class="text-2xl font-bold text-gray-900" id="topSkill">-</p> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-10"> |
| |
| <div class="bg-white rounded-xl shadow-sm p-6"> |
| <h3 class="text-xl font-bold text-gray-900 mb-4">Skills by Category</h3> |
| <canvas id="categoryChart" height="300"></canvas> |
| </div> |
| |
| |
| <div class="bg-white rounded-xl shadow-sm p-6"> |
| <h3 class="text-xl font-bold text-gray-900 mb-4">Skills Distribution</h3> |
| <canvas id="distributionChart" height="300"></canvas> |
| </div> |
| </div> |
|
|
| |
| <div class="bg-white rounded-xl shadow-sm p-6 mb-10"> |
| <h3 class="text-xl font-bold text-gray-900 mb-6">Skill Details</h3> |
| <div id="skillsContainer" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> |
| |
| </div> |
| </div> |
|
|
| |
| <div class="bg-white rounded-xl shadow-sm p-6"> |
| <h3 class="text-xl font-bold text-gray-900 mb-6">Detailed Data</h3> |
| <div class="overflow-x-auto"> |
| <table class="min-w-full divide-y divide-gray-200"> |
| <thead class="bg-gray-50"> |
| <tr> |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Year</th> |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Domain</th> |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Category</th> |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Skill</th> |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Count</th> |
| <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Percentage</th> |
| </tr> |
| </thead> |
| <tbody class="bg-white divide-y divide-gray-200" id="dataTable"> |
| |
| </tbody> |
| </table> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <footer class="bg-white border-t border-gray-200 mt-12"> |
| <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8"> |
| <div class="text-center"> |
| <p class="text-gray-500">© 2023 SkillScape AI Vision. Data visualization dashboard.</p> |
| </div> |
| </div> |
| </footer> |
|
|
| <script> |
| |
| feather.replace(); |
| |
| |
| VANTA.GLOBE({ |
| el: "#vanta-bg", |
| mouseControls: true, |
| touchControls: true, |
| gyroControls: false, |
| minHeight: 200.00, |
| minWidth: 200.00, |
| scale: 1.00, |
| scaleMobile: 1.00, |
| color: 0x6366f1, |
| color2: 0x8b5cf6, |
| backgroundColor: 0xf8fafc |
| }); |
| |
| |
| const rawData = `Year,domain,category,skill,count,percentage |
| 2019,AI,Attitude,eigeninitiative,108,2.26 |
| 2019,AI,Attitude,positiv,4,0.08 |
| 2019,AI,Big data,big data,241,5.05 |
| 2019,AI,Big data,datenmenge,2,0.04 |
| 2019,AI,Big data,hadoop,33,0.69 |
| 2019,AI,Big data,hive,6,0.13 |
| 2019,AI,Big data,mapreduce,2,0.04 |
| 2019,AI,Big data,nosql,15,0.31 |
| 2019,AI,Big data,spark,45,0.94 |
| 2019,AI,Communication General,communication,548,11.49 |
| 2019,AI,Communication General,kommunikation,469,9.83 |
| 2019,AI,Communication General,kommunikativ,3,0.06 |
| 2019,AI,Creativity,creative,15,0.31 |
| 2019,AI,Creativity,innovative,271,5.68 |
| 2019,AI,Creativity,kreativ,16,0.34 |
| 2019,AI,Data mining,classification,3,0.06 |
| 2019,AI,Data mining,data mining,70,1.47 |
| 2019,AI,Data mining,datenanalyse,31,0.65 |
| 2019,AI,Data mining,forecasting,15,0.31 |
| 2019,AI,Data mining,machine learning,296,6.2 |
| 2019,AI,Data mining,maschinelles lernen,16,0.34 |
| 2019,AI,Data mining,prediction,2,0.04 |
| 2019,AI,Decision making,analyse,601,12.6 |
| 2019,AI,Decision making,analysis,99,2.08 |
| 2019,AI,Decision making,analytical,22,0.46 |
| 2019,AI,Decision making,decision making,13,0.27 |
| 2019,AI,Decision making,entscheidungsfindung,4,0.08 |
| 2019,AI,Detail-oriented,accuracy,5,0.1 |
| 2019,AI,Detail-oriented,precision,3,0.06 |
| 2019,AI,Independence,autonom,2,0.04 |
| 2019,AI,Independence,autonomous,21,0.44 |
| 2019,AI,Independence,independent,9,0.19 |
| 2019,AI,Independence,selbstständig,374,7.84 |
| 2019,AI,Interpersonal Personal,personal skills,2,0.04 |
| 2019,AI,Interpersonal Personal,soft skills,2,0.04 |
| 2019,AI,Interpersonal Team,collaboration,42,0.88 |
| 2019,AI,Interpersonal Team,team management,1,0.02 |
| 2019,AI,Interpersonal Team,teamarbeit,11,0.23 |
| 2019,AI,Interpersonal Team,teamwork,5,0.1 |
| 2019,AI,Interpersonal Team,zusammenarbeit,190,3.98 |
| 2019,AI,Motivation,ambition,3,0.06 |
| 2019,AI,Motivation,motivated,22,0.46 |
| 2019,AI,Motivation,motiviert,8,0.17 |
| 2019,AI,Networking,networking,24,0.5 |
| 2019,AI,Networking,netzwerken,22,0.46 |
| 2019,AI,Presentation,present,10,0.21 |
| 2019,AI,Presentation,presentation,4,0.08 |
| 2019,AI,Presentation,präsentation,38,0.8 |
| 2019,AI,Presentation,report,19,0.4 |
| 2019,AI,Problem solving,problem solving,3,0.06 |
| 2019,AI,Problem solving,problemlösung,6,0.13 |
| 2019,AI,Problem solving,troubleshoot,2,0.04 |
| 2019,AI,Process design,continuous improvement,11,0.23 |
| 2019,AI,Process design,process design,6,0.13 |
| 2019,AI,Process design,prozessdesign,6,0.13 |
| 2019,AI,Process design,prozessverbesserung,2,0.04 |
| 2019,AI,Programming,bash,4,0.08 |
| 2019,AI,Programming,java,246,5.16 |
| 2019,AI,Programming,javascript,102,2.14 |
| 2019,AI,Programming,matlab,18,0.38 |
| 2019,AI,Programming,programmierung,88,1.84 |
| 2019,AI,Programming,python,145,3.04 |
| 2019,AI,Programming,scala,20,0.42 |
| 2019,AI,Programming,softwareentwicklung,180,3.77 |
| 2019,AI,Statistics,regression,2,0.04 |
| 2019,AI,Statistics,sas,32,0.67 |
| 2019,AI,Statistics,spss,9,0.19 |
| 2019,AI,Statistics,statistics,23,0.48 |
| 2019,AI,Statistics,statistik,68,1.43 |
| 2019,AI,Statistics,wahrscheinlichkeit,1,0.02 |
| 2019,AI,Time management,deadline,1,0.02 |
| 2019,AI,Time management,zeitmanagement,1,0.02 |
| 2019,AI,Verbal,oral,5,0.1 |
| 2019,AI,Verbal,verbal,2,0.04 |
| 2019,AI,Written,schriftlich,4,0.08 |
| 2019,AI,Written,writing,7,0.15 |
| 2019,AI,Written,written,10,0.21 |
| 2025,AI,Attitude,eigeninitiative,31,0.75 |
| 2025,AI,Attitude,positiv,2,0.05 |
| 2025,AI,Attitude,positive attitude,1,0.02 |
| 2025,AI,Big data,big data,82,1.97 |
| 2025,AI,Big data,hadoop,10,0.24 |
| 2025,AI,Big data,hive,7,0.17 |
| 2025,AI,Big data,nosql,23,0.55 |
| 2025,AI,Big data,spark,48,1.16 |
| 2025,AI,Communication General,communication,192,4.62 |
| 2025,AI,Communication General,communicative,1,0.02 |
| 2025,AI,Communication General,kommunikation,48,1.16 |
| 2025,AI,Communication General,kommunikativ,7,0.17 |
| 2025,AI,Creativity,creative,56,1.35 |
| 2025,AI,Creativity,innovative,259,6.24 |
| 2025,AI,Creativity,kreativ,7,0.17 |
| 2025,AI,Data mining,classification,16,0.39 |
| 2025,AI,Data mining,data mining,24,0.58 |
| 2025,AI,Data mining,datenanalyse,51,1.23 |
| 2025,AI,Data mining,forecasting,20,0.48 |
| 2025,AI,Data mining,machine learning,742,17.87 |
| 2025,AI,Data mining,maschinelles lernen,14,0.34 |
| 2025,AI,Data mining,prediction,20,0.48 |
| 2025,AI,Decision making,analyse,143,3.44 |
| 2025,AI,Decision making,analysis,151,3.64 |
| 2025,AI,Decision making,analytical,82,1.97 |
| 2025,AI,Decision making,decision making,53,1.28 |
| 2025,AI,Decision making,entscheidungsfindung,6,0.14 |
| 2025,AI,Decision making,strategic thinking,6,0.14 |
| 2025,AI,Detail-oriented,accuracy,31,0.75 |
| 2025,AI,Detail-oriented,genauigkeit,8,0.19 |
| 2025,AI,Detail-oriented,precision,13,0.31 |
| 2025,AI,Independence,autonomous,20,0.48 |
| 2025,AI,Independence,independent,46,1.11 |
| 2025,AI,Independence,selbstständig,30,0.72 |
| 2025,AI,Interpersonal Personal,personal skills,1,0.02 |
| 2025,AI,Interpersonal Personal,soft skills,10,0.24 |
| 2025,AI,Interpersonal Team,collaboration,170,4.09 |
| 2025,AI,Interpersonal Team,team management,2,0.05 |
| 2025,AI,Interpersonal Team,teamarbeit,12,0.29 |
| 2025,AI,Interpersonal Team,teamwork,47,1.13 |
| 2025,AI,Interpersonal Team,zusammenarbeit,168,4.05 |
| 2025,AI,Motivation,ambition,5,0.12 |
| 2025,AI,Motivation,motivated,70,1.69 |
| 2025,AI,Motivation,motiviert,12,0.29 |
| 2025,AI,Networking,networking,45,1.08 |
| 2025,AI,Networking,netzwerken,14,0.34 |
| 2025,AI,Presentation,present,36,0.87 |
| 2025,AI,Presentation,presentation,26,0.63 |
| 2025,AI,Presentation,präsentation,18,0.43 |
| 2025,AI,Presentation,report,17,0.41 |
| 2025,AI,Problem solving,critical thinker,1,0.02 |
| 2025,AI,Problem solving,kritisches denken,1,0.02 |
| 2025,AI,Problem solving,problem solving,88,2.12 |
| 2025,AI,Problem solving,problemlösung,4,0.1 |
| 2025,AI,Problem solving,troubleshoot,16,0.39 |
| 2025,AI,Process design,continuous improvement,39,0.94 |
| 2025,AI,Process design,process design,1,0.02 |
| 2025,AI,Process design,prozessdesign,2,0.05 |
| 2025,AI,Process design,prozessverbesserung,2,0.05 |
| 2025,AI,Programming,bash,18,0.43 |
| 2025,AI,Programming,java,86,2.07 |
| 2025,AI,Programming,javascript,42,1.01 |
| 2025,AI,Programming,matlab,24,0.58 |
| 2025,AI,Programming,programmierung,38,0.92 |
| 2025,AI,Programming,python,474,11.41 |
| 2025,AI,Programming,scala,18,0.43 |
| 2025,AI,Programming,softwareentwicklung,63,1.52 |
| 2025,AI,Statistics,regression,11,0.26 |
| 2025,AI,Statistics,sas,6,0.14 |
| 2025,AI,Statistics,spss,1,0.02 |
| 2025,AI,Statistics,stata,2,0.05 |
| 2025,AI,Statistics,statistics,52,1.25 |
| 2025,AI,Statistics,statistik,54,1.3 |
| 2025,AI,Time management,deadline,12,0.29 |
| 2025,AI,Time management,fristgerecht,1,0.02 |
| 2025,AI,Time management,time management,6,0.14 |
| 2025,AI,Verbal,mündlich,7,0.17 |
| 2025,AI,Verbal,oral,10,0.24 |
| 2025,AI,Verbal,verbal,31,0.75 |
| 2025,AI,Written,schriftlich,9,0.22 |
| 2025,AI,Written,writing,44,1.06 |
| 2025,AI,Written,written,87,2.09 |
| 2025,ML,Attitude,eigeninitiative,2,2.5 |
| 2025,ML,Big data,big data,1,1.25 |
| 2025,ML,Big data,hadoop,1,1.25 |
| 2025,ML,Big data,spark,1,1.25 |
| 2025,ML,Communication General,kommunikation,4,5.0 |
| 2025,ML,Creativity,innovative,3,3.75 |
| 2025,ML,Data mining,datenanalyse,3,3.75 |
| 2025,ML,Data mining,forecasting,1,1.25 |
| 2025,ML,Data mining,machine learning,18,22.5 |
| 2025,ML,Decision making,analyse,9,11.25 |
| 2025,ML,Decision making,entscheidungsfindung,2,2.5 |
| 2025,ML,Independence,autonom,1,1.25 |
| 2025,ML,Interpersonal Team,teamarbeit,1,1.25 |
| 2025,ML,Interpersonal Team,zusammenarbeit,8,10.0 |
| 2025,ML,Motivation,motiviert,1,1.25 |
| 2025,ML,Presentation,präsentation,1,1.25 |
| 2025,ML,Presentation,report,1,1.25 |
| 2025,ML,Programming,bash,1,1.25 |
| 2025,ML,Programming,java,2,2.5 |
| 2025,ML,Programming,programmierung,2,2.5 |
| 2025,ML,Programming,python,11,13.75 |
| 2025,ML,Programming,softwareentwicklung,4,5.0 |
| 2025,ML,Statistics,statistik,2,2.5`; |
| |
| |
| const parseCSV = (csv) => { |
| const lines = csv.trim().split('\n'); |
| const headers = lines[0].split(','); |
| return lines.slice(1).map(line => { |
| const values = line.split(','); |
| const obj = {}; |
| headers.forEach((header, index) => { |
| obj[header] = values[index]; |
| }); |
| return obj; |
| }); |
| }; |
| |
| const data = parseCSV(rawData); |
| |
| |
| const categories = [...new Set(data.map(item => item.category))]; |
| const categoryFilter = document.getElementById('categoryFilter'); |
| categories.forEach(category => { |
| const option = document.createElement('option'); |
| option.value = category; |
| option.textContent = category; |
| categoryFilter.appendChild(option); |
| }); |
| |
| |
| let categoryChart, distributionChart; |
| |
| |
| const renderCharts = (filteredData) => { |
| |
| const categoryData = {}; |
| filteredData.forEach(item => { |
| if (!categoryData[item.category]) { |
| categoryData[item.category] = 0; |
| } |
| categoryData[item.category] += parseInt(item.count); |
| }); |
| |
| const categories = Object.keys(categoryData); |
| const counts = Object.values(categoryData); |
| |
| const ctx1 = document.getElementById('categoryChart').getContext('2d'); |
| if (categoryChart) categoryChart.destroy(); |
| categoryChart = new Chart(ctx1, { |
| type: 'bar', |
| data: { |
| labels: categories, |
| datasets: [{ |
| label: 'Skill Count', |
| data: counts, |
| backgroundColor: 'rgba(99, 102, 241, 0.7)', |
| borderColor: 'rgba(99, 102, 241, 1)', |
| borderWidth: 1 |
| }] |
| }, |
| options: { |
| responsive: true, |
| scales: { |
| y: { |
| beginAtZero: true |
| } |
| } |
| } |
| }); |
| |
| |
| const domainData = {}; |
| filteredData.forEach(item => { |
| if (!domainData[item.domain]) { |
| domainData[item.domain] = 0; |
| } |
| domainData[item.domain] += parseInt(item.count); |
| }); |
| |
| const domains = Object.keys(domainData); |
| const domainCounts = Object.values(domainData); |
| |
| const ctx2 = document.getElementById('distributionChart').getContext('2d'); |
| if (distributionChart) distributionChart.destroy(); |
| distributionChart = new Chart(ctx2, { |
| type: 'doughnut', |
| data: { |
| labels: domains, |
| datasets: [{ |
| data: domainCounts, |
| backgroundColor: [ |
| 'rgba(99, 102, 241, 0.7)', |
| 'rgba(139, 92, 246, 0.7)', |
| 'rgba(16, 185, 129, 0.7)', |
| 'rgba(245, 158, 11, 0.7)' |
| ], |
| borderColor: [ |
| 'rgba(99, 102, 241, 1)', |
| 'rgba(139, 92, 246, 1)', |
| 'rgba(16, 185, 129, 1)', |
| 'rgba(245, 158, 11, 1)' |
| ], |
| borderWidth: 1 |
| }] |
| }, |
| options: { |
| responsive: true, |
| plugins: { |
| legend: { |
| position: 'right', |
| } |
| } |
| } |
| }); |
| }; |
| |
| |
| const renderSkillsGrid = (filteredData) => { |
| const container = document.getElementById('skillsContainer'); |
| container.innerHTML = ''; |
| |
| |
| const sortedData = [...filteredData].sort((a, b) => parseInt(b.count) - parseInt(a.count)); |
| |
| sortedData.slice(0, 12).forEach(item => { |
| const skillCard = document.createElement('div'); |
| skillCard.className = 'skill-card bg-white rounded-xl shadow-sm border border-gray-100 p-5'; |
| skillCard.innerHTML = ` |
| <div class="flex justify-between items-start mb-3"> |
| <span class="domain-badge text-white text-xs font-medium px-2.5 py-0.5 rounded">${item.domain}</span> |
| <span class="text-gray-500 text-sm">${item.year}</span> |
| </div> |
| <h4 class="font-bold text-gray-900 mb-1">${item.skill}</h4> |
| <p class="text-gray-500 text-sm mb-3">${item.category}</p> |
| <div class="mb-2"> |
| <div class="flex justify-between text-sm mb-1"> |
| <span>Count: ${item.count}</span> |
| <span>${item.percentage}%</span> |
| </div> |
| <div class="w-full bg-gray-200 rounded-full h-2"> |
| <div class="progress-bar bg-primary h-2 rounded-full" style="width: ${Math.min(100, item.percentage * 5)}%"></div> |
| </div> |
| </div> |
| `; |
| container.appendChild(skillCard); |
| }); |
| }; |
| |
| |
| const renderDataTable = (filteredData) => { |
| const tbody = document.getElementById('dataTable'); |
| tbody.innerHTML = ''; |
| |
| |
| const sortedData = [...filteredData].sort((a, b) => parseInt(b.count) - parseInt(a.count)); |
| |
| sortedData.slice(0, 20).forEach(item => { |
| const row = document.createElement('tr'); |
| row.innerHTML = ` |
| <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item.year}</td> |
| <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">${item.domain}</td> |
| <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item.category}</td> |
| <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">${item.skill}</td> |
| <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item.count}</td> |
| <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item.percentage}%</td> |
| `; |
| tbody.appendChild(row); |
| }); |
| }; |
| |
| |
| const updateMetrics = (filteredData) => { |
| const totalSkills = filteredData.reduce((sum, item) => sum + parseInt(item.count), 0); |
| document.getElementById('totalSkills').textContent = totalSkills; |
| |
| |
| const categoryData = {}; |
| filteredData.forEach(item => { |
| if (!categoryData[item.category]) { |
| categoryData[item.category] = 0; |
| } |
| categoryData[item.category] += parseInt(item.count); |
| }); |
| |
| const topCategory = Object.keys(categoryData).reduce((a, b) => categoryData[a] > categoryData[b] ? a : b); |
| document.getElementById('topCategory').textContent = topCategory; |
| |
| |
| const topSkill = filteredData.reduce((prev, current) => (parseInt(prev.count) > parseInt(current.count)) ? prev : current); |
| document.getElementById('topSkill').textContent = topSkill.skill; |
| |
| |
| const data2019 = filteredData.filter(item => item.year === '2019'); |
| const data2025 = filteredData.filter(item => item.year === '2025'); |
| |
| const total2019 = data2019.reduce((sum, item) => sum + parseInt(item.count), 0); |
| const total2025 = data2025.reduce((sum, item) => sum + parseInt(item.count), 0); |
| |
| const growthRate = total2019 > 0 ? (((total2025 - total2019) / total2019) * 100).toFixed(1) : 0; |
| document.getElementById('growthRate').textContent = `${growthRate > 0 ? '+' : ''}${growthRate}%`; |
| }; |
| |
| |
| const filterData = () => { |
| const year = document.getElementById('yearFilter').value; |
| const domain = document.getElementById('domainFilter').value; |
| const category = document.getElementById('categoryFilter').value; |
| |
| let filteredData = data; |
| |
| if (year !== 'all') { |
| filteredData = filteredData.filter(item => item.year === year); |
| } |
| |
| if (domain !== 'all') { |
| filteredData = filteredData.filter(item => item.domain === domain); |
| } |
| |
| if (category !== 'all') { |
| filteredData = filteredData.filter(item => item.category === category); |
| } |
| |
| renderCharts(filteredData); |
| renderSkillsGrid(filteredData); |
| renderDataTable(filteredData); |
| updateMetrics(filteredData); |
| }; |
| |
| |
| document.addEventListener('DOMContentLoaded', () => { |
| filterData(); |
| |
| |
| document.getElementById('yearFilter').addEventListener('change', filterData); |
| document.getElementById('domainFilter').addEventListener('change', filterData); |
| document.getElementById('categoryFilter').addEventListener('change', filterData); |
| }); |
| </script> |
| </body> |
| </html> |
|
|