TreeTrack / static /welcome.html
RoyAalekh's picture
chore(cache): auto-bump cache version before push
5b479e0
raw
history blame
19.6 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TreeTrack - Forest Research Platform</title>
<link rel="stylesheet" href="/static/css/design-system.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<!-- Leaflet CSS for interactive map -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" crossorigin="">
<style>
/* Conference Welcome Screen Styles */
:root {
--forest-primary: #1a2e1a;
--forest-secondary: #2d4a2d;
--earth-accent: #4a5d4a;
--sky-light: #f0f6f0;
--soft-red: #dc3545;
--cream-white: #fefefe;
}
body {
margin: 0;
font-family: 'Inter', sans-serif;
min-height: 100vh;
overflow-x: hidden;
position: relative;
}
/* Background Map Display */
#background-map {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 0;
opacity: 0;
transition: opacity 1s ease-in-out;
}
#background-map.loaded {
opacity: 1;
}
/* Overlay for better text contrast */
.map-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(135deg,
rgba(26, 46, 26, 0.75) 0%,
rgba(45, 74, 45, 0.65) 60%,
rgba(74, 93, 74, 0.7) 100%);
z-index: 1;
pointer-events: none;
}
/* Content overlay with enhanced glassmorphism */
.content-overlay {
position: relative;
z-index: 2;
min-height: 100vh;
backdrop-filter: blur(1px);
}
/* Hero Section */
.hero-section {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
position: relative;
background: transparent;
}
.welcome-container {
max-width: 1200px;
width: 90%;
text-align: center;
color: white;
z-index: 2;
}
.hero-badge {
display: inline-block;
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
padding: 8px 20px;
border-radius: 50px;
font-size: 0.875rem;
font-weight: 500;
margin-bottom: 2rem;
border: 1px solid rgba(255, 255, 255, 0.2);
}
.hero-title {
font-size: clamp(3rem, 8vw, 5rem);
font-weight: 700;
margin-bottom: 1rem;
line-height: 1.1;
background: linear-gradient(135deg, white, rgba(255, 255, 255, 0.8));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.hero-subtitle {
font-size: clamp(1.125rem, 3vw, 1.5rem);
margin-bottom: 1rem;
opacity: 0.9;
font-weight: 400;
}
.hero-description {
font-size: 1.125rem;
margin-bottom: 3rem;
opacity: 0.8;
max-width: 600px;
margin-left: auto;
margin-right: auto;
line-height: 1.6;
}
/* Exploration Grid */
.exploration-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1.5rem;
margin-top: 3rem;
max-width: 1000px;
margin-left: auto;
margin-right: auto;
}
.exploration-card {
background: rgba(255, 255, 255, 0.12);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.25);
border-radius: 1rem;
padding: 2rem;
cursor: pointer;
transition: all 0.3s ease;
text-align: center;
position: relative;
overflow: hidden;
min-height: 180px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
}
.exploration-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: linear-gradient(90deg, var(--energy-orange), var(--earth-accent));
transform: scaleX(0);
transition: transform 0.3s ease;
}
.exploration-card:hover::before {
transform: scaleX(1);
}
.exploration-card:hover {
transform: translateY(-3px);
background: rgba(255, 255, 255, 0.18);
border-color: rgba(255, 255, 255, 0.35);
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.25);
}
.exploration-card:hover .card-icon {
background: rgba(255, 255, 255, 0.25);
border-color: rgba(255, 255, 255, 0.5);
transform: translateY(-2px);
}
.card-icon {
width: 60px;
height: 60px;
background: rgba(255, 255, 255, 0.15);
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto 1.5rem auto;
font-size: 0.75rem;
font-weight: 500;
color: rgba(255, 255, 255, 0.9);
letter-spacing: 0.5px;
transition: all 0.3s ease;
}
.card-title {
font-size: 1.25rem;
font-weight: 600;
margin-bottom: 0.75rem;
color: white;
}
.card-description {
font-size: 1rem;
opacity: 0.9;
line-height: 1.6;
text-align: center;
margin-bottom: 0;
}
/* Research Context */
.research-context {
background: rgba(255, 255, 255, 0.08);
backdrop-filter: blur(15px);
-webkit-backdrop-filter: blur(15px);
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 1rem;
padding: 1.5rem;
margin-top: 3rem;
text-align: center;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
}
.context-badge {
background: var(--energy-orange);
color: white;
padding: 4px 12px;
border-radius: 20px;
font-size: 0.75rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
display: inline-block;
margin-bottom: 1rem;
}
.context-text {
font-size: 1rem;
opacity: 0.9;
line-height: 1.6;
}
/* Responsive Design */
@media (max-width: 1024px) and (min-width: 769px) {
.exploration-grid {
gap: 1rem;
}
.exploration-card {
padding: 1.5rem;
min-height: 160px;
}
}
@media (max-width: 768px) {
.welcome-container {
width: 95%;
}
.exploration-grid {
grid-template-columns: 1fr;
gap: 1.5rem;
}
.exploration-card {
padding: 1.5rem;
}
}
/* Loading Animation */
.card-loading {
opacity: 0.7;
pointer-events: none;
}
.card-loading::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 20px;
height: 20px;
margin: -10px 0 0 -10px;
border: 2px solid transparent;
border-top: 2px solid white;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Logout Button */
.logout-btn {
position: fixed;
top: 2rem;
right: 2rem;
z-index: 1000;
background: rgba(220, 53, 69, 0.9);
color: white;
border: 1px solid rgba(255, 255, 255, 0.3);
padding: 0.75rem 1.5rem;
border-radius: 0.5rem;
cursor: pointer;
font-weight: 600;
font-size: 0.875rem;
backdrop-filter: blur(10px);
transition: all 0.2s ease;
}
.logout-btn:hover {
background: rgba(185, 28, 28, 0.95);
transform: translateY(-1px);
box-shadow: 0 4px 15px rgba(220, 53, 69, 0.3);
}
@media (max-width: 768px) {
.logout-btn {
top: 1rem;
right: 1rem;
padding: 0.5rem 1rem;
font-size: 0.8rem;
}
}
</style>
</head>
<body>
<!-- Background Map -->
<div id="background-map"></div>
<!-- Overlay for Better Text Contrast -->
<div class="map-overlay"></div>
<!-- Content Overlay -->
<div class="content-overlay">
<!-- Logout Button -->
<button class="logout-btn" id="logoutBtn">Logout</button>
<div class="hero-section">
<div class="welcome-container">
<div class="hero-badge">Phase 1 Research • Tezpur, Assam</div>
<h1 class="hero-title">TreeTrack</h1>
<div class="hero-subtitle">Welcome to TreeTrack!</div>
<p class="hero-description">
This app is designed for data collection and visualisation of various tree species and their distribution.<br>
Here, you can explore Phase 1 of tree mapping efforts from various locations within Tezpur, Assam.
</p>
<div class="exploration-grid">
<div class="exploration-card" id="exploreForm" onclick="exploreDataCollection()">
<div class="card-icon">FORM</div>
<div class="card-title">Data Collection Form</div>
<div class="card-description">
View the data collection form used in the project
</div>
</div>
<div class="exploration-card" id="exploreMap" onclick="exploreTreeMap()">
<div class="card-icon">MAP</div>
<div class="card-title">Interactive Tree Map</div>
<div class="card-description">
View an interactive map showing geotagged trees from Tezpur, Assam
</div>
</div>
<div class="exploration-card" id="exploreContributors" onclick="exploreContributors()">
<div class="card-icon">TEAM</div>
<div class="card-title">Contributors</div>
<div class="card-description">
Meet the research team and project contributors
</div>
</div>
</div>
<!-- Get in Touch Section -->
<div class="research-context">
<div class="context-badge">Get in Touch</div>
<div class="context-text">
<p style="margin-bottom: 1rem;">Thank you!</p>
<p style="margin-bottom: 1rem;">Would you like to map trees in your own area?</p>
<p style="margin-bottom: 1rem;">Do you think this app could be useful to you?</p>
<p style="margin-bottom: 0;">Share your thoughts or suggestions at <a href="mailto:youthforforest2@gmail.com" style="color: rgba(255, 255, 255, 0.9); text-decoration: underline;">youthforforest2@gmail.com</a></p>
</div>
</div>
</div>
</div>
</div>
<!-- Leaflet JavaScript -->
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" crossorigin=""></script>
<script>
// Initialize Background Map Display
function initializeMap() {
// Tezpur, Assam coordinates
const tezpurCoords = [26.6340, 92.7840];
// Create map instance for background display
const map = L.map('background-map', {
center: tezpurCoords,
zoom: 12,
zoomControl: false,
scrollWheelZoom: false,
doubleClickZoom: false,
boxZoom: false,
keyboard: false,
dragging: false,
touchZoom: false,
attributionControl: false
});
// Disable all interactions for decorative display only
map.getContainer().style.cursor = 'default';
// Add satellite/terrain tile layer for background
const satelliteLayer = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
maxZoom: 19,
attribution: false
});
const terrainLayer = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {
maxZoom: 17,
attribution: false
});
// Use satellite as primary, terrain as fallback
satelliteLayer.on('tileerror', function() {
console.log('Satellite layer failed, switching to terrain...');
map.removeLayer(satelliteLayer);
terrainLayer.addTo(map);
});
satelliteLayer.addTo(map);
// Add decorative markers for Tezpur area
const areaPoints = [
{coords: [26.6340, 92.7840], name: "Tezpur Center"},
{coords: [26.6500, 92.7900], name: "Research Area North"},
{coords: [26.6200, 92.7700], name: "Research Area South"},
{coords: [26.6400, 92.8000], name: "Research Area East"}
];
areaPoints.forEach(point => {
L.circleMarker(point.coords, {
radius: 3,
fillColor: '#8ab070',
color: '#739b5a',
weight: 1,
opacity: 0.6,
fillOpacity: 0.4
}).addTo(map);
});
// Fade in map when tiles are loaded
satelliteLayer.on('load', function() {
setTimeout(() => {
document.getElementById('background-map').classList.add('loaded');
}, 500);
});
// Fallback fade-in after 3 seconds
setTimeout(() => {
document.getElementById('background-map').classList.add('loaded');
}, 3000);
}
// Navigation functions
function exploreDataCollection() {
console.log('Exploring data collection form...');
const card = document.getElementById('exploreForm');
card.classList.add('card-loading');
// Try /form first, fallback to / if needed
window.location.href = '/form';
}
function exploreTreeMap() {
console.log('Exploring tree map...');
const card = document.getElementById('exploreMap');
card.classList.add('card-loading');
window.location.href = '/map';
}
function exploreContributors() {
console.log('Exploring contributors page...');
const card = document.getElementById('exploreContributors');
card.classList.add('card-loading');
window.location.href = '/contributors';
}
// Logout function
async function logout() {
try {
const token = localStorage.getItem('auth_token');
if (token) {
await fetch('/api/auth/logout', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`
}
});
}
} catch (error) {
console.error('Logout error:', error);
} finally {
localStorage.removeItem('auth_token');
localStorage.removeItem('user_info');
window.location.href = '/login';
}
}
// Enhanced mobile interactions
if ('ontouchstart' in window) {
document.querySelectorAll('.exploration-card').forEach(card => {
card.addEventListener('touchstart', function() {
this.style.transform = 'translateY(-2px)';
});
card.addEventListener('touchend', function() {
setTimeout(() => {
this.style.transform = '';
}, 150);
});
});
}
// Keyboard navigation
document.addEventListener('keydown', function(e) {
if (e.key === '1') exploreDataCollection();
if (e.key === '2') exploreTreeMap();
if (e.key === '3') exploreContributors();
if (e.key === 'Escape') window.location.reload();
});
// Demo session management
function setupDemoSession() {
// Set session marker
sessionStorage.setItem('demo_session', 'active');
sessionStorage.setItem('session_start', Date.now());
// Auto-refresh every 8 hours to prevent stale sessions
setTimeout(() => {
window.location.reload();
}, 8 * 60 * 60 * 1000);
}
// Initialize demo mode
setupDemoSession();
// Initialize map when page loads
document.addEventListener('DOMContentLoaded', function() {
// Small delay to ensure DOM is fully ready
setTimeout(initializeMap, 200);
// Setup logout button
const logoutBtn = document.getElementById('logoutBtn');
if (logoutBtn) {
logoutBtn.addEventListener('click', logout);
}
});
// Fallback initialization
window.addEventListener('load', function() {
if (!document.getElementById('background-map').hasChildNodes()) {
initializeMap();
}
});
</script>
</body>
</html>