|
|
<!DOCTYPE html> |
|
|
<html lang="en"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>View Tracking Results</title> |
|
|
<link rel="stylesheet" href="../style.css"> |
|
|
<script src="https://cdn.tailwindcss.com"></script> |
|
|
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script> |
|
|
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places"></script> |
|
|
<script src="../components/navbar.js"></script> |
|
|
<script src="../components/footer.js"></script> |
|
|
</head> |
|
|
<body class="bg-gray-50 min-h-screen flex flex-col"> |
|
|
<custom-navbar></custom-navbar> |
|
|
|
|
|
<main class="flex-grow container mx-auto px-4 py-8"> |
|
|
<div class="max-w-4xl mx-auto bg-white rounded-xl shadow-md overflow-hidden p-6"> |
|
|
<div class="text-center mb-8"> |
|
|
<h1 class="text-3xl font-bold text-gray-800 mb-2">View Tracking Results</h1> |
|
|
<p class="text-gray-600">Enter your tracking token to view results</p> |
|
|
</div> |
|
|
|
|
|
<div class="bg-gray-100 p-6 rounded-lg"> |
|
|
<form id="tokenForm" class="space-y-4"> |
|
|
<div> |
|
|
<label for="trackingToken" class="block text-sm font-medium text-gray-700 mb-1">Tracking Token</label> |
|
|
<input type="text" id="trackingToken" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500" placeholder="xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx" required> |
|
|
</div> |
|
|
<button type="submit" class="w-full bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-md transition duration-200 flex items-center justify-center"> |
|
|
<i data-feather="search" class="mr-2"></i> View Results |
|
|
</button> |
|
|
</form> |
|
|
</div> |
|
|
|
|
|
<div id="resultsContainer" class="hidden mt-8"> |
|
|
|
|
|
</div> |
|
|
</div> |
|
|
</main> |
|
|
|
|
|
<custom-footer></custom-footer> |
|
|
<script> |
|
|
document.addEventListener('DOMContentLoaded', function() { |
|
|
feather.replace(); |
|
|
|
|
|
const tokenForm = document.getElementById('tokenForm'); |
|
|
const resultsContainer = document.getElementById('resultsContainer'); |
|
|
|
|
|
tokenForm.addEventListener('submit', function(e) { |
|
|
e.preventDefault(); |
|
|
const token = document.getElementById('trackingToken').value.trim(); |
|
|
|
|
|
// Show loading state |
|
|
const submitButton = tokenForm.querySelector('button[type="submit"]'); |
|
|
const originalButtonText = submitButton.innerHTML; |
|
|
submitButton.innerHTML = `<i data-feather="loader" class="loading-spinner mr-2"></i> Searching...`; |
|
|
feather.replace(); |
|
|
|
|
|
// Simulate API call delay |
|
|
setTimeout(() => { |
|
|
// Get tracking result from database |
|
|
const trackingResult = getTrackingResult(token); |
|
|
|
|
|
if (trackingResult) { |
|
|
displayTrackingResults(trackingResult); |
|
|
} else { |
|
|
resultsContainer.innerHTML = ` |
|
|
<div class="bg-red-50 border-l-4 border-red-500 p-4"> |
|
|
<div class="flex"> |
|
|
<div class="flex-shrink-0"> |
|
|
<i data-feather="alert-triangle" class="h-5 w-5 text-red-500"></i> |
|
|
</div> |
|
|
<div class="ml-3"> |
|
|
<p class="text-sm text-red-700"> |
|
|
No tracking results found for this token. The link may not have been opened yet. |
|
|
</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
`; |
|
|
feather.replace(); |
|
|
} |
|
|
|
|
|
resultsContainer.classList.remove('hidden'); |
|
|
submitButton.innerHTML = originalButtonText; |
|
|
feather.replace(); |
|
|
}, 1000); |
|
|
}); |
|
|
|
|
|
function displayTrackingResults(result) { |
|
|
const userData = result.userData; |
|
|
resultsContainer.innerHTML = ` |
|
|
<div class="grid md:grid-cols-2 gap-8"> |
|
|
<div class="space-y-6"> |
|
|
<div class="bg-gray-100 p-6 rounded-lg"> |
|
|
<h2 class="text-xl font-semibold text-gray-800 mb-4">Tracking Details</h2> |
|
|
<div class="text-sm space-y-2"> |
|
|
<div><span class="font-medium">Original URL:</span> <a href="${result.originalUrl}" target="_blank" class="text-blue-600 hover:underline">${result.originalUrl}</a></div> |
|
|
<div><span class="font-medium">Time Opened:</span> ${new Date(result.accessedAt).toLocaleString()}</div> |
|
|
<div><span class="font-medium">IP Address:</span> ${userData.ip}</div> |
|
|
<div><span class="font-medium">Location:</span> ${userData.location.city}, ${userData.location.country}</div> |
|
|
<div><span class="font-medium">Device:</span> ${userData.device.platform}</div> |
|
|
<div><span class="font-medium">Browser:</span> ${userData.browser.language}</div> |
|
|
<div><span class="font-medium">Screen:</span> ${userData.device.screen.width}x${userData.device.screen.height}</div> |
|
|
<div><span class="font-medium">Referrer:</span> ${userData.browser.referrer || 'Direct'}</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
<div class="space-y-6"> |
|
|
<div id="mapContainer" class="bg-gray-100 p-4 rounded-lg h-64"> |
|
|
<div id="map" class="h-full w-full"></div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
`; |
|
|
|
|
|
// Initialize map |
|
|
const map = new google.maps.Map(document.getElementById("map"), { |
|
|
center: { lat: userData.location.latitude, lng: userData.location.longitude }, |
|
|
zoom: 8, |
|
|
}); |
|
|
|
|
|
new google.maps.Marker({ |
|
|
position: { lat: userData.location.latitude, lng: userData.location.longitude }, |
|
|
map: map, |
|
|
title: "Visitor Location" |
|
|
}); |
|
|
} |
|
|
}); |
|
|
|
|
|
// Database functions (simplified version from script.js) |
|
|
function getTrackingResult(token) { |
|
|
let db = JSON.parse(localStorage.getItem('db') || '{}'); |
|
|
if (!db.trackingResults) return null; |
|
|
return db.trackingResults.find(r => r.token === token); |
|
|
} |
|
|
</script> |
|
|
</body> |
|
|
</html> |