Initial commit: Lead Scraper - Google Maps

This commit is contained in:
Mambo
2026-02-11 01:48:37 +01:00
commit 831d63b7e8
13 changed files with 2406 additions and 0 deletions

77
views/leads.ejs Normal file
View File

@@ -0,0 +1,77 @@
<!DOCTYPE html>
<html lang="en" class="bg-dark">
<head><%- include('partials/head') %></head>
<body class="bg-dark text-gray-200 flex min-h-screen">
<% const activePage = 'leads'; %>
<%- include('partials/sidebar') %>
<main class="flex-1 ml-56 p-6">
<div class="flex items-center justify-between mb-4">
<h2 class="text-lg font-bold">Saved Leads</h2>
<span class="text-xs text-gray-500"><%= leads.length %> leads</span>
</div>
<% if (!leads || leads.length === 0) { %>
<div class="flex flex-col items-center justify-center py-24 text-gray-500">
<svg class="w-16 h-16 mb-4 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1" d="M5 5a2 2 0 012-2h10a2 2 0 012 2v16l-7-3.5L5 21V5z"/></svg>
<p class="text-sm font-medium">No saved leads</p>
<p class="text-xs mt-1">Bookmark businesses from search results to save them here</p>
<a href="/" class="mt-4 bg-accent hover:bg-accent-hover text-white px-4 py-2 rounded-lg text-sm transition-colors">Search Leads</a>
</div>
<% } else { %>
<div class="overflow-x-auto rounded-lg border border-white/5">
<table class="w-full text-sm">
<thead>
<tr class="bg-card text-gray-400 text-left text-xs uppercase tracking-wider">
<th class="px-4 py-3">Business</th>
<th class="px-4 py-3">Phone</th>
<th class="px-4 py-3">Email</th>
<th class="px-4 py-3">Website</th>
<th class="px-4 py-3">Rating</th>
<th class="px-4 py-3">Saved</th>
<th class="px-4 py-3 w-10"></th>
</tr>
</thead>
<tbody class="divide-y divide-white/5">
<% leads.forEach(l => { %>
<tr class="hover:bg-card-hover transition-colors" id="lead-<%= l.placeId %>">
<td class="px-4 py-3">
<p class="font-medium text-white"><%= l.title %></p>
<p class="text-xs text-gray-500"><%= l.categoryName %></p>
</td>
<td class="px-4 py-3 text-gray-300"><%= l.phone || '—' %></td>
<td class="px-4 py-3 text-gray-300"><%= l.email || '—' %></td>
<td class="px-4 py-3">
<% if (l.website) { %>
<a href="<%= l.website %>" target="_blank" class="text-accent hover:underline truncate block max-w-[200px]"><%= l.website.replace(/^https?:\/\//, '').replace(/\/$/, '') %></a>
<% } else { %>—<% } %>
</td>
<td class="px-4 py-3">
<% if (l.totalScore) { %>
<span class="text-yellow-400">★</span> <%= l.totalScore.toFixed(1) %>
<span class="text-gray-500">(<%= l.reviewsCount %>)</span>
<% } else { %>—<% } %>
</td>
<td class="px-4 py-3 text-xs text-gray-500"><%= new Date(l.savedAt).toLocaleDateString() %></td>
<td class="px-4 py-3">
<button onclick="removeLead('<%= l.placeId %>')" class="text-red-400 hover:text-red-300 transition-colors" title="Remove">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/></svg>
</button>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
<% } %>
</main>
<script>
async function removeLead(placeId) {
await fetch('/api/leads/' + encodeURIComponent(placeId), { method: 'DELETE' });
const row = document.getElementById('lead-' + placeId);
if (row) row.remove();
}
</script>
</body>
</html>