|
|
<!DOCTYPE html> |
|
|
<html lang="en"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>Dark Store Placement & Heatmap</title> |
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"> |
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" /> |
|
|
<style> |
|
|
body { |
|
|
font-family: 'Poppins', sans-serif; |
|
|
background: url('https://wallpapercave.com/wp/wp4411792.jpg') no-repeat center center fixed; |
|
|
background-size: cover; |
|
|
color: #ffffff; |
|
|
margin: 0; |
|
|
padding: 0; |
|
|
} |
|
|
.container { |
|
|
background: rgba(255, 255, 255, 0.1); |
|
|
backdrop-filter: blur(15px); |
|
|
padding: 30px; |
|
|
border-radius: 15px; |
|
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); |
|
|
text-align: center; |
|
|
max-width: 900px; |
|
|
margin: 40px auto; |
|
|
border: 1px solid rgba(255, 255, 255, 0.2); |
|
|
} |
|
|
h2 { |
|
|
font-weight: 600; |
|
|
text-transform: uppercase; |
|
|
background: linear-gradient(90deg, #ff416c, #ff4b2b); |
|
|
-webkit-background-clip: text; |
|
|
-webkit-text-fill-color: transparent; |
|
|
} |
|
|
.file-upload { |
|
|
position: relative; |
|
|
display: inline-block; |
|
|
} |
|
|
.file-upload input[type="file"] { |
|
|
position: absolute; |
|
|
opacity: 0; |
|
|
width: 100%; |
|
|
height: 100%; |
|
|
cursor: pointer; |
|
|
} |
|
|
.file-upload label { |
|
|
display: flex; |
|
|
align-items: center; |
|
|
justify-content: center; |
|
|
padding: 12px 20px; |
|
|
background: linear-gradient(135deg, #007bff, #00d4ff); |
|
|
color: #fff; |
|
|
font-weight: 600; |
|
|
border-radius: 8px; |
|
|
cursor: pointer; |
|
|
transition: all 0.3s ease; |
|
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); |
|
|
} |
|
|
.btn { |
|
|
padding: 12px 24px; |
|
|
font-size: 16px; |
|
|
font-weight: 600; |
|
|
border-radius: 8px; |
|
|
text-transform: uppercase; |
|
|
transition: all 0.3s ease-in-out; |
|
|
cursor: pointer; |
|
|
} |
|
|
.btn-primary { |
|
|
background: linear-gradient(135deg, #007bff, #00d4ff); |
|
|
color: #fff; |
|
|
} |
|
|
.btn-danger { |
|
|
background: linear-gradient(135deg, #ff416c, #ff4b2b); |
|
|
color: #fff; |
|
|
} |
|
|
.btn:hover { |
|
|
transform: translateY(-3px); |
|
|
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4); |
|
|
} |
|
|
#map, #heatmap { |
|
|
height: 500px; |
|
|
border-radius: 10px; |
|
|
overflow: hidden; |
|
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3); |
|
|
margin-top: 20px; |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body> |
|
|
<div class="container mt-4"> |
|
|
<h2 class="text-center"> Dark Store Placement & Heatmap</h2> |
|
|
|
|
|
<div class="mb-3"> |
|
|
<label class="form-label">Upload CSV File (Latitude, Longitude, Location)</label> |
|
|
<div class="file-upload"> |
|
|
<input type="file" id="csvFileInput"> |
|
|
<label for="csvFileInput">Choose File</label> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="d-flex justify-content-center gap-3"> |
|
|
<button class="btn btn-primary" onclick="processCSV()">Generate Store Map</button> |
|
|
<button class="btn btn-danger" onclick="generateHeatmap()">Generate Heatmap</button> |
|
|
</div> |
|
|
|
|
|
<div id="map" class="mt-4"></div> |
|
|
<h3 class="text-center mt-4">🔥 Heatmap Representation</h3> |
|
|
<div id="heatmap" class="mt-2"></div> |
|
|
</div> |
|
|
|
|
|
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script> |
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.3.2/papaparse.min.js"></script> |
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.heat/0.2.0/leaflet-heat.js"></script> |
|
|
|
|
|
<script> |
|
|
let map = L.map('map').setView([18.5204, 73.8567], 10); |
|
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map); |
|
|
|
|
|
let heatmapMap = L.map('heatmap').setView([18.5204, 73.8567], 10); |
|
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(heatmapMap); |
|
|
|
|
|
let selectedLocations = []; |
|
|
let heatLayer; |
|
|
|
|
|
function processCSV() { |
|
|
const fileInput = document.getElementById("csvFileInput"); |
|
|
if (!fileInput.files.length) return alert("Please upload a CSV file"); |
|
|
|
|
|
Papa.parse(fileInput.files[0], { |
|
|
header: true, |
|
|
skipEmptyLines: true, |
|
|
complete: function (result) { |
|
|
let data = result.data; |
|
|
selectedLocations = []; |
|
|
|
|
|
data.forEach(row => { |
|
|
let lat = parseFloat(row.Latitude); |
|
|
let lon = parseFloat(row.Longitude); |
|
|
let location = row.Location; |
|
|
|
|
|
selectedLocations.push([lat, lon, 1.0]); |
|
|
L.marker([lat, lon]).addTo(map) |
|
|
.bindPopup(`<b>${location}</b><br>Lat: ${lat}, Lon: ${lon}`); |
|
|
}); |
|
|
} |
|
|
}); |
|
|
} |
|
|
|
|
|
function generateHeatmap() { |
|
|
if (heatLayer) heatmapMap.removeLayer(heatLayer); |
|
|
|
|
|
heatLayer = L.heatLayer(selectedLocations, { |
|
|
radius: 25, |
|
|
blur: 15, |
|
|
maxZoom: 10 |
|
|
}).addTo(heatmapMap); |
|
|
} |
|
|
</script> |
|
|
</body> |
|
|
</html> |
|
|
|