linked-agent / index.html
Jensin's picture
Update index.html
06d0269 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LinkedIn Profile Scraper | 10K Profiles per Batch</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<script>
tailwind.config = {
darkMode: 'class',
theme: {
extend: {
colors: {
linkedin: '#0A66C2',
primary: '#0A66C2',
secondary: '#378FE9',
accent: '#16437E',
dark: '#1D2226',
light: '#F5F5F5',
darkBg: '#12181D',
darkCard: '#1D2933'
}
}
}
}
</script>
<style>
.scraper-card {
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
border-radius: 16px;
transition: all 0.3s ease;
}
.scraper-card:hover {
transform: translateY(-5px);
box-shadow: 0 20px 30px -10px rgba(0, 0, 0, 0.15);
}
.progress-bar {
height: 8px;
border-radius: 4px;
overflow: hidden;
background-color: #e0e0e0;
}
.progress-fill {
height: 100%;
border-radius: 4px;
background: linear-gradient(90deg, #0A66C2, #378FE9);
transition: width 0.5s ease;
}
.profile-card {
transition: all 0.2s ease;
border-left: 4px solid #0A66C2;
}
.profile-card:hover {
transform: translateX(5px);
background-color: #f8fafc;
}
.dark .profile-card:hover {
background-color: #1f2a33;
}
.scrape-btn {
background: linear-gradient(135deg, #0A66C2, #16437E);
transition: all 0.3s ease;
}
.scrape-btn:hover {
transform: scale(1.02);
box-shadow: 0 10px 20px -5px rgba(10, 102, 194, 0.4);
}
.scrape-btn:active {
transform: scale(0.98);
}
.tab-btn {
transition: all 0.2s ease;
border-bottom: 3px solid transparent;
}
.tab-btn.active {
border-bottom-color: #0A66C2;
color: #0A66C2;
}
.result-grid {
display: grid;
grid-template-columns: 1fr;
gap: 1rem;
}
@media (min-width: 640px) {
.result-grid {
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 1.5rem;
}
}
.animate-pulse {
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.floating-notification {
animation: floatUp 0.5s ease-out forwards;
}
@keyframes floatUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.skeleton {
background-color: #e2e8f0;
border-radius: 4px;
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
.dark .skeleton {
background-color: #2d3748;
}
.dark-mode-toggle {
transition: all 0.3s ease;
}
.dark-mode-toggle:hover {
transform: rotate(15deg);
}
.stat-card:hover .stat-icon {
transform: scale(1.1) rotate(5deg);
}
.stat-icon {
transition: all 0.3s ease;
}
.tooltip {
position: relative;
display: inline-block;
}
.tooltip .tooltip-text {
visibility: hidden;
width: 200px;
background-color: #1D2226;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 8px;
position: absolute;
z-index: 1;
bottom: 125%;
left: 50%;
transform: translateX(-50%);
opacity: 0;
transition: opacity 0.3s;
font-size: 0.875rem;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
}
.tooltip:hover .tooltip-text {
visibility: visible;
opacity: 1;
}
.dark .tooltip .tooltip-text {
background-color: #2d3748;
}
.mobile-menu {
transform: translateX(-100%);
transition: transform 0.3s ease;
}
.mobile-menu.open {
transform: translateX(0);
}
.export-btn {
transition: all 0.2s ease;
}
.export-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
}
.pagination-btn {
transition: all 0.2s ease;
}
.pagination-btn:hover:not(.disabled) {
background-color: #e5e7eb;
transform: translateY(-2px);
}
.dark .pagination-btn:hover:not(.disabled) {
background-color: #2d3748;
}
</style>
</head>
<body class="bg-gray-50 min-h-screen dark:bg-darkBg">
<!-- Header -->
<header class="bg-white shadow-sm dark:bg-darkCard">
<div class="container mx-auto px-4 py-4 flex justify-between items-center">
<div class="flex items-center">
<div class="bg-primary p-2 rounded-lg mr-3">
<i class="fab fa-linkedin text-white text-2xl"></i>
</div>
<h1 class="text-2xl font-bold text-gray-800 dark:text-gray-200">LinkedIn<span class="text-primary">Scraper</span></h1>
</div>
<nav>
<ul class="hidden md:flex space-x-6">
<li><a href="#" class="text-gray-600 hover:text-primary font-medium dark:text-gray-300 dark:hover:text-secondary">Dashboard</a></li>
<li><a href="#" class="text-gray-600 hover:text-primary font-medium dark:text-gray-300 dark:hover:text-secondary">Scrape History</a></li>
<li><a href="#" class="text-gray-600 hover:text-primary font-medium dark:text-gray-300 dark:hover:text-secondary">API</a></li>
<li><a href="#" class="text-gray-600 hover:text-primary font-medium dark:text-gray-300 dark:hover:text-secondary">Help</a></li>
</ul>
<button id="mobileMenuBtn" class="md:hidden text-gray-600 dark:text-gray-300">
<i class="fas fa-bars text-xl"></i>
</button>
</nav>
<div class="flex items-center">
<button class="bg-primary hover:bg-secondary text-white px-4 py-2 rounded-lg font-medium flex items-center mr-4">
<i class="fas fa-user-plus mr-2"></i> Upgrade
</button>
<button id="darkModeToggle" class="dark-mode-toggle bg-gray-200 dark:bg-gray-700 p-2 rounded-full mr-4">
<i class="fas fa-moon text-gray-700 dark:text-yellow-300"></i>
</button>
<div class="relative">
<div class="w-10 h-10 rounded-full bg-gray-200 dark:bg-gray-700 flex items-center justify-center cursor-pointer">
<i class="fas fa-user text-gray-600 dark:text-gray-300"></i>
</div>
<div class="absolute right-0 bottom-0 w-3 h-3 bg-green-500 rounded-full border-2 border-white dark:border-darkCard"></div>
</div>
</div>
</div>
</header>
<!-- Mobile Menu -->
<div id="mobileMenu" class="mobile-menu fixed inset-0 z-50 bg-black bg-opacity-50 hidden">
<div class="bg-white dark:bg-darkCard w-64 h-full p-4">
<div class="flex justify-between items-center mb-8">
<h3 class="text-xl font-bold text-gray-800 dark:text-gray-200">Menu</h3>
<button id="closeMobileMenu" class="p-2 text-gray-600 dark:text-gray-300">
<i class="fas fa-times text-xl"></i>
</button>
</div>
<ul class="space-y-4">
<li><a href="#" class="text-gray-600 hover:text-primary font-medium block py-2 dark:text-gray-300 dark:hover:text-secondary">Dashboard</a></li>
<li><a href="#" class="text-gray-600 hover:text-primary font-medium block py-2 dark:text-gray-300 dark:hover:text-secondary">Scrape History</a></li>
<li><a href="#" class="text-gray-600 hover:text-primary font-medium block py-2 dark:text-gray-300 dark:hover:text-secondary">API</a></li>
<li><a href="#" class="text-gray-600 hover:text-primary font-medium block py-2 dark:text-gray-300 dark:hover:text-secondary">Help</a></li>
<li class="pt-4">
<button class="bg-primary hover:bg-secondary text-white px-4 py-2 rounded-lg font-medium flex items-center w-full">
<i class="fas fa-user-plus mr-2"></i> Upgrade Account
</button>
</li>
</ul>
</div>
</div>
<!-- Main Content -->
<main class="container mx-auto px-4 py-8">
<div class="text-center mb-10">
<h2 class="text-4xl font-bold text-gray-800 dark:text-gray-200 mb-3">LinkedIn Profile Scraper</h2>
<p class="text-xl text-gray-600 dark:text-gray-400 max-w-3xl mx-auto">Extract up to 10,000 LinkedIn profiles per batch with professional details including name, title, company, location, and more.</p>
</div>
<!-- Stats Cards -->
<div class="grid grid-cols-2 sm:grid-cols-4 gap-4 sm:gap-6 mb-8">
<div class="scraper-card stat-card bg-white dark:bg-darkCard p-6 rounded-xl">
<div class="flex justify-between items-center">
<div>
<p class="text-gray-500 dark:text-gray-400 text-sm">Total Scraped</p>
<h3 class="text-2xl font-bold text-gray-800 dark:text-gray-200">124,856</h3>
</div>
<div class="bg-blue-100 dark:bg-blue-900 p-3 rounded-lg">
<i class="fas fa-database text-primary dark:text-blue-300 text-xl stat-icon"></i>
</div>
</div>
</div>
<div class="scraper-card stat-card bg-white dark:bg-darkCard p-6 rounded-xl">
<div class="flex justify-between items-center">
<div>
<p class="text-gray-500 dark:text-gray-400 text-sm">This Month</p>
<h3 class="text-2xl font-bold text-gray-800 dark:text-gray-200">8,420</h3>
</div>
<div class="bg-green-100 dark:bg-green-900 p-3 rounded-lg">
<i class="fas fa-chart-line text-green-500 dark:text-green-300 text-xl stat-icon"></i>
</div>
</div>
</div>
<div class="scraper-card stat-card bg-white dark:bg-darkCard p-6 rounded-xl">
<div class="flex justify-between items-center">
<div>
<p class="text-gray-500 dark:text-gray-400 text-sm">Batch Size</p>
<h3 class="text-2xl font-bold text-gray-800 dark:text-gray-200">10,000</h3>
</div>
<div class="bg-purple-100 dark:bg-purple-900 p-3 rounded-lg">
<i class="fas fa-layer-group text-purple-500 dark:text-purple-300 text-xl stat-icon"></i>
</div>
</div>
</div>
<div class="scraper-card stat-card bg-white dark:bg-darkCard p-6 rounded-xl">
<div class="flex justify-between items-center">
<div>
<p class="text-gray-500 dark:text-gray-400 text-sm">Success Rate</p>
<h3 class="text-2xl font-bold text-gray-800 dark:text-gray-200">98.7%</h3>
</div>
<div class="bg-yellow-100 dark:bg-yellow-900 p-3 rounded-lg">
<i class="fas fa-check-circle text-yellow-500 dark:text-yellow-300 text-xl stat-icon"></i>
</div>
</div>
</div>
</div>
<!-- Scraper Interface -->
<div class="scraper-card bg-white dark:bg-darkCard p-6 md:p-8 rounded-xl mb-8">
<div class="flex flex-wrap mb-6 border-b dark:border-gray-700">
<button class="tab-btn px-4 py-2 font-medium text-gray-600 dark:text-gray-300 mr-4 active">New Scrape</button>
<button class="tab-btn px-4 py-2 font-medium text-gray-600 dark:text-gray-300 mr-4">Saved Templates</button>
<button class="tab-btn px-4 py-2 font-medium text-gray-600 dark:text-gray-300">Advanced Filters</button>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4 sm:gap-6 mb-6">
<div>
<label class="block text-gray-700 dark:text-gray-300 font-medium mb-2">Search Keywords</label>
<input type="text" class="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent dark:bg-gray-800 dark:text-gray-200" placeholder="e.g., Software Engineer, Marketing Manager">
</div>
<div>
<label class="block text-gray-700 dark:text-gray-300 font-medium mb-2">Location</label>
<input type="text" class="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent dark:bg-gray-800 dark:text-gray-200" placeholder="e.g., United States, San Francisco">
</div>
<div>
<label class="block text-gray-700 dark:text-gray-300 font-medium mb-2">Industry</label>
<select class="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent dark:bg-gray-800 dark:text-gray-200">
<option value="">All Industries</option>
<option value="it">Information Technology</option>
<option value="finance">Finance</option>
<option value="healthcare">Healthcare</option>
<option value="education">Education</option>
<option value="marketing">Marketing</option>
</select>
</div>
<div>
<label class="block text-gray-700 dark:text-gray-300 font-medium mb-2">Company Size</label>
<select class="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent dark:bg-gray-800 dark:text-gray-200">
<option value="">All Sizes</option>
<option value="1-10">1-10 employees</option>
<option value="11-50">11-50 employees</option>
<option value="51-200">51-200 employees</option>
<option value="201-500">201-500 employees</option>
<option value="501+">501+ employees</option>
</select>
</div>
</div>
<div class="mb-6">
<label class="block text-gray-700 dark:text-gray-300 font-medium mb-2">Number of Profiles</label>
<div class="flex flex-col sm:flex-row items-start sm:items-center gap-3 sm:gap-4">
<input type="range" min="100" max="10000" step="100" value="5000" class="w-full sm:mr-4 dark:accent-primary" id="profileRange">
<div class="bg-gray-100 dark:bg-gray-800 px-4 py-2 rounded-lg w-full sm:w-auto text-center dark:text-gray-200">
<span id="profileCount">5,000</span> profiles
</div>
</div>
<div class="text-sm text-gray-500 dark:text-gray-400 mt-2">Max 10,000 profiles per batch</div>
</div>
<div class="flex flex-wrap items-center justify-between">
<div class="flex items-center mb-4 md:mb-0">
<input type="checkbox" id="includeContact" class="mr-2 h-5 w-5 text-primary rounded focus:ring-primary dark:bg-gray-800">
<label for="includeContact" class="text-gray-700 dark:text-gray-300">Include contact information</label>
</div>
<button id="scrapeBtn" class="scrape-btn text-white px-8 py-3 rounded-lg font-semibold flex items-center w-full sm:w-auto justify-center">
<i class="fas fa-bolt mr-2"></i>
<span id="scrapeBtnText">Start Scraping</span>
<span id="scrapeSpinner" class="ml-2 hidden">
<i class="fas fa-spinner fa-spin"></i>
</span>
</button>
</div>
</div>
<!-- Progress Section -->
<div id="progressSection" class="scraper-card bg-white dark:bg-darkCard p-6 md:p-8 rounded-xl mb-8 hidden">
<h3 class="text-xl font-bold text-gray-800 dark:text-gray-200 mb-4">Scraping in Progress</h3>
<div class="mb-4">
<div class="flex justify-between mb-2">
<span class="text-gray-700 dark:text-gray-300">Extracting profiles...</span>
<span id="progressPercent" class="text-primary font-medium">0%</span>
</div>
<div class="progress-bar">
<div id="progressFill" class="progress-fill" style="width: 0%"></div>
</div>
</div>
<div class="grid grid-cols-2 sm:grid-cols-4 gap-3 sm:gap-4 mt-6">
<div class="text-center p-4 bg-gray-50 dark:bg-gray-800 rounded-lg">
<div class="text-2xl font-bold text-primary" id="profilesScraped">0</div>
<div class="text-gray-600 dark:text-gray-400">Profiles Scraped</div>
</div>
<div class="text-center p-4 bg-gray-50 dark:bg-gray-800 rounded-lg">
<div class="text-2xl font-bold text-green-500" id="successRate">0%</div>
<div class="text-gray-600 dark:text-gray-400">Success Rate</div>
</div>
<div class="text-center p-4 bg-gray-50 dark:bg-gray-800 rounded-lg">
<div class="text-2xl font-bold text-gray-800 dark:text-gray-200" id="timeElapsed">0s</div>
<div class="text-gray-600 dark:text-gray-400">Time Elapsed</div>
</div>
<div class="text-center p-4 bg-gray-50 dark:bg-gray-800 rounded-lg">
<div class="text-2xl font-bold text-gray-800 dark:text-gray-200" id="timeRemaining">~30s</div>
<div class="text-gray-600 dark:text-gray-400">Estimated Time</div>
</div>
</div>
</div>
<!-- Results Section -->
<div id="resultsSection" class="hidden">
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4 mb-6">
<h3 class="text-2xl font-bold text-gray-800 dark:text-gray-200">Scraping Results</h3>
<div class="flex flex-col sm:flex-row gap-2 sm:gap-3 w-full sm:w-auto">
<button class="export-btn bg-white dark:bg-darkCard border border-gray-300 dark:border-gray-700 px-4 py-2 rounded-lg font-medium flex items-center justify-center">
<i class="fas fa-download mr-2"></i> Export CSV
</button>
<button class="export-btn bg-white dark:bg-darkCard border border-gray-300 dark:border-gray-700 px-4 py-2 rounded-lg font-medium flex items-center justify-center">
<i class="fas fa-file-excel mr-2"></i> Export Excel
</button>
</div>
</div>
<div class="result-grid mb-8" id="resultGrid">
<!-- Profile cards will be inserted here by JavaScript -->
</div>
<div class="flex flex-col sm:flex-row justify-between items-center bg-white dark:bg-darkCard p-4 rounded-lg">
<div class="text-gray-600 dark:text-gray-400 mb-4 sm:mb-0">
Showing <span id="showingCount">10</span> of <span id="totalCount">5,000</span> profiles
</div>
<div class="flex flex-wrap justify-center gap-2">
<button class="pagination-btn px-4 py-2 bg-gray-100 dark:bg-gray-800 rounded-lg disabled:opacity-50 disabled:cursor-not-allowed" id="prevPageBtn" disabled>
<i class="fas fa-chevron-left"></i>
</button>
<button class="pagination-btn px-4 py-2 bg-primary text-white rounded-lg">1</button>
<button class="pagination-btn px-4 py-2 bg-gray-100 dark:bg-gray-800 rounded-lg">2</button>
<button class="pagination-btn px-4 py-2 bg-gray-100 dark:bg-gray-800 rounded-lg">3</button>
<button class="pagination-btn px-4 py-2 bg-gray-100 dark:bg-gray-800 rounded-lg">...</button>
<button class="pagination-btn px-4 py-2 bg-gray-100 dark:bg-gray-800 rounded-lg">50</button>
<button class="pagination-btn px-4 py-2 bg-gray-100 dark:bg-gray-800 rounded-lg" id="nextPageBtn">
<i class="fas fa-chevron-right"></i>
</button>
</div>
</div>
</div>
<!-- Notification -->
<div id="notification" class="fixed bottom-4 right-4 bg-green-500 text-white px-6 py-3 rounded-lg shadow-lg hidden">
<i class="fas fa-check-circle mr-2"></i>
<span>Scraping completed successfully!</span>
</div>
</main>
<!-- Footer -->
<footer class="bg-dark text-gray-300 py-8 mt-12">
<div class="container mx-auto px-4">
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6 sm:gap-8">
<div>
<h4 class="text-white text-lg font-semibold mb-4">LinkedIn Scraper</h4>
<p class="mb-4">Professional LinkedIn data extraction tool for recruiters, marketers, and sales professionals.</p>
<div class="flex space-x-4">
<a href="#" class="text-gray-400 hover:text-white"><i class="fab fa-twitter"></i></a>
<a href="#" class="text-gray-400 hover:text-white"><i class="fab fa-facebook"></i></a>
<a href="#" class="text-gray-400 hover:text-white"><i class="fab fa-linkedin"></i></a>
</div>
</div>
<div>
<h4 class="text-white text-lg font-semibold mb-4">Features</h4>
<ul class="space-y-2">
<li><a href="#" class="hover:text-white">Profile Scraping</a></li>
<li><a href="#" class="hover:text-white">Company Data</a></li>
<li><a href="#" class="hover:text-white">Email Extraction</a></li>
<li><a href="#" class="hover:text-white">Bulk Processing</a></li>
</ul>
</div>
<div>
<h4 class="text-white text-lg font-semibold mb-4">Resources</h4>
<ul class="space-y-2">
<li><a href="#" class="hover:text-white">Documentation</a></li>
<li><a href="#" class="hover:text-white">API Reference</a></li>
<li><a href="#" class="hover:text-white">Tutorials</a></li>
<li><a href="#" class="hover:text-white">Blog</a></li>
</ul>
</div>
<div>
<h4 class="text-white text-lg font-semibold mb-4">Legal</h4>
<ul class="space-y-2">
<li><a href="#" class="hover:text-white">Privacy Policy</a></li>
<li><a href="#" class="hover:text-white">Terms of Service</a></li>
<li><a href="#" class="hover:text-white">Compliance</a></li>
<li><a href="#" class="hover:text-white">GDPR</a></li>
</ul>
</div>
</div>
<div class="border-t border-gray-700 mt-8 pt-6 text-center">
<p>&copy; 2023 LinkedInScraper. All rights reserved.</p>
</div>
</div>
</footer>
<script>
// DOM Elements
const profileRange = document.getElementById('profileRange');
const profileCount = document.getElementById('profileCount');
const scrapeBtn = document.getElementById('scrapeBtn');
const scrapeBtnText = document.getElementById('scrapeBtnText');
const scrapeSpinner = document.getElementById('scrapeSpinner');
const progressSection = document.getElementById('progressSection');
const resultsSection = document.getElementById('resultsSection');
const progressFill = document.getElementById('progressFill');
const progressPercent = document.getElementById('progressPercent');
const profilesScraped = document.getElementById('profilesScraped');
const successRate = document.getElementById('successRate');
const timeElapsed = document.getElementById('timeElapsed');
const timeRemaining = document.getElementById('timeRemaining');
const notification = document.getElementById('notification');
const resultGrid = document.getElementById('resultGrid');
const darkModeToggle = document.getElementById('darkModeToggle');
const mobileMenuBtn = document.getElementById('mobileMenuBtn');
const mobileMenu = document.getElementById('mobileMenu');
const closeMobileMenu = document.getElementById('closeMobileMenu');
const prevPageBtn = document.getElementById('prevPageBtn');
const nextPageBtn = document.getElementById('nextPageBtn');
const showingCount = document.getElementById('showingCount');
const totalCount = document.getElementById('totalCount');
// Update profile count display
profileRange.addEventListener('input', function() {
const count = parseInt(this.value).toLocaleString();
profileCount.textContent = count;
});
// Dark mode toggle
darkModeToggle.addEventListener('click', function() {
document.documentElement.classList.toggle('dark');
const isDark = document.documentElement.classList.contains('dark');
localStorage.setItem('darkMode', isDark);
// Update icon
const icon = darkModeToggle.querySelector('i');
if (isDark) {
icon.classList.remove('fa-moon');
icon.classList.add('fa-sun');
} else {
icon.classList.remove('fa-sun');
icon.classList.add('fa-moon');
}
});
// Check for saved dark mode preference
if (localStorage.getItem('darkMode') === 'true') {
document.documentElement.classList.add('dark');
const icon = darkModeToggle.querySelector('i');
icon.classList.remove('fa-moon');
icon.classList.add('fa-sun');
}
// Mobile menu toggle
mobileMenuBtn.addEventListener('click', function() {
mobileMenu.classList.remove('hidden');
setTimeout(() => {
mobileMenu.classList.add('open');
}, 10);
});
closeMobileMenu.addEventListener('click', function() {
mobileMenu.classList.remove('open');
setTimeout(() => {
mobileMenu.classList.add('hidden');
}, 300);
});
// Close mobile menu when clicking outside
mobileMenu.addEventListener('click', function(e) {
if (e.target === mobileMenu) {
mobileMenu.classList.remove('open');
setTimeout(() => {
mobileMenu.classList.add('hidden');
}, 300);
}
});
// Scrape button handler
scrapeBtn.addEventListener('click', function() {
// Show spinner and change text
scrapeSpinner.classList.remove('hidden');
scrapeBtnText.textContent = 'Scraping...';
scrapeBtn.disabled = true;
// Show progress section
progressSection.classList.remove('hidden');
// Hide results if shown
resultsSection.classList.add('hidden');
// Reset progress
let progress = 0;
let elapsed = 0;
let scraped = 0;
const totalProfiles = parseInt(profileRange.value);
const successPercent = 98 + Math.random() * 1.3; // Random success rate between 98-99.3%
// Show skeleton loaders
showSkeletonLoaders(totalProfiles);
// Start progress simulation
const interval = setInterval(() => {
progress += 1;
elapsed += 1;
scraped = Math.floor(totalProfiles * (progress/100));
// Update progress bar
progressFill.style.width = `${progress}%`;
progressPercent.textContent = `${progress}%`;
profilesScraped.textContent = scraped.toLocaleString();
successRate.textContent = `${successPercent.toFixed(1)}%`;
timeElapsed.textContent = `${elapsed}s`;
// Calculate remaining time
const remaining = Math.max(1, Math.floor((100 - progress) * elapsed / progress));
timeRemaining.textContent = `~${remaining}s`;
// When progress completes
if (progress >= 100) {
clearInterval(interval);
// Reset button
scrapeSpinner.classList.add('hidden');
scrapeBtnText.textContent = 'Start Scraping';
scrapeBtn.disabled = false;
// Show notification
notification.classList.remove('hidden');
notification.classList.add('floating-notification');
// Hide notification after 3 seconds
setTimeout(() => {
notification.classList.add('hidden');
notification.classList.remove('floating-notification');
}, 3000);
// Show results after a delay
setTimeout(() => {
progressSection.classList.add('hidden');
resultsSection.classList.remove('hidden');
populateResults(totalProfiles);
}, 1000);
}
}, 50); // Update every 50ms
});
// Show skeleton loaders
function showSkeletonLoaders(total) {
resultGrid.innerHTML = '';
// Update counts
showingCount.textContent = '10';
totalCount.textContent = total.toLocaleString();
// Generate skeleton cards
for (let i = 0; i < 10; i++) {
const card = document.createElement('div');
card.className = 'profile-card bg-white dark:bg-darkCard p-5 rounded-lg shadow-sm';
card.innerHTML = `
<div class="flex items-start mb-4">
<div class="skeleton w-16 h-16 rounded-full"></div>
<div class="ml-4 flex-1">
<div class="skeleton h-5 w-3/4 mb-2"></div>
<div class="skeleton h-4 w-1/2"></div>
</div>
</div>
<div class="grid grid-cols-2 gap-3 mb-4">
<div class="flex items-center">
<div class="skeleton w-4 h-4 mr-2"></div>
<div class="skeleton h-4 w-3/4"></div>
</div>
<div class="flex items-center">
<div class="skeleton w-4 h-4 mr-2"></div>
<div class="skeleton h-4 w-3/4"></div>
</div>
<div class="flex items-center">
<div class="skeleton w-4 h-4 mr-2"></div>
<div class="skeleton h-4 w-3/4"></div>
</div>
<div class="flex items-center">
<div class="skeleton w-4 h-4 mr-2"></div>
<div class="skeleton h-4 w-3/4"></div>
</div>
</div>
<div class="flex justify-between">
<div class="skeleton h-8 w-24"></div>
<div class="skeleton h-8 w-24"></div>
</div>
`;
resultGrid.appendChild(card);
}
}
// Populate results with mock data
function populateResults(total) {
// Clear existing results
resultGrid.innerHTML = '';
// Update counts
showingCount.textContent = '10';
totalCount.textContent = total.toLocaleString();
// Generate mock profile cards
const titles = [
'Senior Software Engineer',
'Marketing Director',
'Product Manager',
'Data Scientist',
'UX Designer',
'Sales Executive',
'HR Specialist',
'Financial Analyst',
'Operations Manager',
'Content Strategist'
];
const companies = [
'Google', 'Microsoft', 'Amazon', 'Apple', 'Meta',
'Netflix', 'Adobe', 'Salesforce', 'IBM', 'Intel'
];
const locations = [
'San Francisco, CA', 'New York, NY', 'Seattle, WA',
'Austin, TX', 'Boston, MA', 'Chicago, IL', 'Los Angeles, CA'
];
for (let i = 0; i < 10; i++) {
const title = titles[Math.floor(Math.random() * titles.length)];
const company = companies[Math.floor(Math.random() * companies.length)];
const location = locations[Math.floor(Math.random() * locations.length)];
const card = document.createElement('div');
card.className = 'profile-card bg-white dark:bg-darkCard p-5 rounded-lg shadow-sm';
card.innerHTML = `
<div class="flex items-start mb-4">
<div class="bg-gray-200 dark:bg-gray-700 rounded-xl w-16 h-16 flex items-center justify-center">
<i class="fas fa-user text-gray-500 dark:text-gray-400 text-xl"></i>
</div>
<div class="ml-4">
<h4 class="font-bold text-lg text-gray-800 dark:text-gray-200">${getRandomName()}</h4>
<p class="text-gray-600 dark:text-gray-400">${title} at ${company}</p>
</div>
</div>
<div class="grid grid-cols-2 gap-3 mb-4">
<div class="flex items-center">
<i class="fas fa-building text-gray-500 dark:text-gray-400 mr-2"></i>
<span class="text-gray-700 dark:text-gray-300">${company}</span>
</div>
<div class="flex items-center">
<i class="fas fa-map-marker-alt text-gray-500 dark:text-gray-400 mr-2"></i>
<span class="text-gray-700 dark:text-gray-300">${location}</span>
</div>
<div class="flex items-center">
<i class="fas fa-briefcase text-gray-500 dark:text-gray-400 mr-2"></i>
<span class="text-gray-700 dark:text-gray-300">${Math.floor(Math.random() * 15) + 3} years exp</span>
</div>
<div class="flex items-center">
<i class="fas fa-user-friends text-gray-500 dark:text-gray-400 mr-2"></i>
<span class="text-gray-700 dark:text-gray-300">${(Math.floor(Math.random() * 500) + 100).toLocaleString()}+ connections</span>
</div>
</div>
<div class="flex justify-between">
<button class="text-primary hover:text-secondary font-medium">
<i class="fas fa-envelope mr-1"></i> Contact
</button>
<button class="text-gray-600 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200">
<i class="fas fa-save mr-1"></i> Save Profile
</button>
</div>
`;
resultGrid.appendChild(card);
}
}
// Generate random names
function getRandomName() {
const firstNames = ['James', 'Mary', 'John', 'Patricia', 'Robert', 'Jennifer', 'Michael', 'Linda', 'William', 'Elizabeth'];
const lastNames = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis', 'Rodriguez', 'Martinez'];
const firstName = firstNames[Math.floor(Math.random() * firstNames.length)];
const lastName = lastNames[Math.floor(Math.random() * lastNames.length)];
return `${firstName} ${lastName}`;
}
// Pagination functionality
prevPageBtn.addEventListener('click', function() {
// In a real app, this would fetch previous page data
alert('Previous page functionality would be implemented here');
});
nextPageBtn.addEventListener('click', function() {
// In a real app, this would fetch next page data
alert('Next page functionality would be implemented here');
});
</script>
</html>