mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 07:11:08 -05:00
530 lines
15 KiB
HTML
530 lines
15 KiB
HTML
<!-- Reusable Location Popup Component for Maps -->
|
|
<div class="location-popup {% if popup_classes %}{{ popup_classes }}{% endif %}"
|
|
data-location-id="{{ location.id }}"
|
|
data-location-type="{{ location.type }}">
|
|
|
|
<!-- Popup Header -->
|
|
<div class="popup-header">
|
|
<h3 class="popup-title">{{ location.name|default:"Unknown Location" }}</h3>
|
|
{% if location.type %}
|
|
<span class="popup-type-badge popup-type-{{ location.type }}">
|
|
{% if location.type == 'park' %}
|
|
<i class="mr-1 fas fa-tree"></i>Park
|
|
{% elif location.type == 'ride' %}
|
|
<i class="mr-1 fas fa-rocket"></i>Ride
|
|
{% elif location.type == 'company' %}
|
|
<i class="mr-1 fas fa-building"></i>Company
|
|
{% else %}
|
|
<i class="mr-1 fas fa-map-marker-alt"></i>Location
|
|
{% endif %}
|
|
</span>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Location Information -->
|
|
{% if location.formatted_location %}
|
|
<div class="popup-meta">
|
|
<i class="fas fa-map-marker-alt mr-1"></i>{{ location.formatted_location }}
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Distance (if applicable) -->
|
|
{% if location.distance %}
|
|
<div class="popup-meta">
|
|
<i class="fas fa-route mr-1"></i>{{ location.distance|floatformat:1 }} miles away
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Type-specific Content -->
|
|
{% if location.type == 'park' %}
|
|
<!-- Park-specific popup content -->
|
|
{% if location.status %}
|
|
<div class="popup-meta">
|
|
<span class="popup-status-badge popup-status-{% if location.status == 'OPERATING' %}operating{% elif location.status == 'CLOSED_TEMP' or location.status == 'CLOSED_PERM' %}closed{% elif location.status == 'UNDER_CONSTRUCTION' %}construction{% else %}demolished{% endif %}">
|
|
{% if location.status == 'OPERATING' %}
|
|
<i class="mr-1 fas fa-check-circle"></i>Operating
|
|
{% elif location.status == 'CLOSED_TEMP' %}
|
|
<i class="mr-1 fas fa-clock"></i>Temporarily Closed
|
|
{% elif location.status == 'CLOSED_PERM' %}
|
|
<i class="mr-1 fas fa-times-circle"></i>Permanently Closed
|
|
{% elif location.status == 'UNDER_CONSTRUCTION' %}
|
|
<i class="mr-1 fas fa-hard-hat"></i>Under Construction
|
|
{% elif location.status == 'DEMOLISHED' %}
|
|
<i class="mr-1 fas fa-ban"></i>Demolished
|
|
{% endif %}
|
|
</span>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if location.operator %}
|
|
<div class="popup-meta">
|
|
<i class="fas fa-building mr-1"></i>{{ location.operator }}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if location.ride_count %}
|
|
<div class="popup-meta">
|
|
<i class="fas fa-rocket mr-1"></i>{{ location.ride_count }} ride{{ location.ride_count|pluralize }}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if location.average_rating %}
|
|
<div class="popup-meta">
|
|
<i class="fas fa-star mr-1 text-yellow-500"></i>{{ location.average_rating|floatformat:1 }}/10 rating
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if location.opening_date %}
|
|
<div class="popup-meta">
|
|
<i class="fas fa-calendar mr-1"></i>Opened {{ location.opening_date.year }}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% elif location.type == 'ride' %}
|
|
<!-- Ride-specific popup content -->
|
|
{% if location.park_name %}
|
|
<div class="popup-meta">
|
|
<i class="fas fa-tree mr-1"></i>{{ location.park_name }}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if location.manufacturer %}
|
|
<div class="popup-meta">
|
|
<i class="fas fa-industry mr-1"></i>{{ location.manufacturer }}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if location.designer %}
|
|
<div class="popup-meta">
|
|
<i class="fas fa-drafting-compass mr-1"></i>{{ location.designer }}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if location.opening_date %}
|
|
<div class="popup-meta">
|
|
<i class="fas fa-calendar mr-1"></i>Opened {{ location.opening_date.year }}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if location.status %}
|
|
<div class="popup-meta">
|
|
<span class="popup-status-badge popup-status-{% if location.status == 'OPERATING' %}operating{% elif location.status == 'CLOSED' %}closed{% elif location.status == 'UNDER_CONSTRUCTION' %}construction{% else %}demolished{% endif %}">
|
|
{% if location.status == 'OPERATING' %}
|
|
<i class="mr-1 fas fa-check-circle"></i>Operating
|
|
{% elif location.status == 'CLOSED' %}
|
|
<i class="mr-1 fas fa-times-circle"></i>Closed
|
|
{% elif location.status == 'UNDER_CONSTRUCTION' %}
|
|
<i class="mr-1 fas fa-hard-hat"></i>Under Construction
|
|
{% elif location.status == 'DEMOLISHED' %}
|
|
<i class="mr-1 fas fa-ban"></i>Demolished
|
|
{% endif %}
|
|
</span>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% elif location.type == 'company' %}
|
|
<!-- Company-specific popup content -->
|
|
{% if location.company_type %}
|
|
<div class="popup-meta">
|
|
<i class="fas fa-tag mr-1"></i>{{ location.get_company_type_display }}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if location.founded_year %}
|
|
<div class="popup-meta">
|
|
<i class="fas fa-calendar mr-1"></i>Founded {{ location.founded_year }}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if location.parks_count %}
|
|
<div class="popup-meta">
|
|
<i class="fas fa-tree mr-1"></i>{{ location.parks_count }} park{{ location.parks_count|pluralize }}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if location.rides_count %}
|
|
<div class="popup-meta">
|
|
<i class="fas fa-rocket mr-1"></i>{{ location.rides_count }} ride{{ location.rides_count|pluralize }}
|
|
</div>
|
|
{% endif %}
|
|
{% endif %}
|
|
|
|
<!-- Custom Content -->
|
|
{% if custom_content %}
|
|
<div class="popup-custom">
|
|
{{ custom_content|safe }}
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Action Buttons -->
|
|
<div class="popup-actions">
|
|
{% if show_details_button %}
|
|
<a href="{{ location.get_absolute_url }}"
|
|
class="popup-btn popup-btn-primary">
|
|
<i class="mr-1 fas fa-info-circle"></i>{{ details_button_text|default:"View Details" }}
|
|
</a>
|
|
{% endif %}
|
|
|
|
{% if show_nearby_button and location.latitude and location.longitude %}
|
|
<a href="{% url 'maps:nearby_locations' %}?lat={{ location.latitude }}&lng={{ location.longitude }}&radius=25"
|
|
class="popup-btn popup-btn-secondary">
|
|
<i class="mr-1 fas fa-search-location"></i>{{ nearby_button_text|default:"Find Nearby" }}
|
|
</a>
|
|
{% endif %}
|
|
|
|
{% if show_directions_button and location.latitude and location.longitude %}
|
|
<button onclick="getDirections({{ location.latitude }}, {{ location.longitude }})"
|
|
class="popup-btn popup-btn-secondary">
|
|
<i class="mr-1 fas fa-directions"></i>{{ directions_button_text|default:"Directions" }}
|
|
</button>
|
|
{% endif %}
|
|
|
|
{% if show_trip_button %}
|
|
<button onclick="addLocationToTrip({{ location|safe }})"
|
|
class="popup-btn popup-btn-accent">
|
|
<i class="mr-1 fas fa-plus"></i>{{ trip_button_text|default:"Add to Trip" }}
|
|
</button>
|
|
{% endif %}
|
|
|
|
{% if show_share_button %}
|
|
<button onclick="shareLocation('{{ location.type }}', {{ location.id }})"
|
|
class="popup-btn popup-btn-secondary">
|
|
<i class="mr-1 fas fa-share"></i>{{ share_button_text|default:"Share" }}
|
|
</button>
|
|
{% endif %}
|
|
|
|
<!-- Custom Action Buttons -->
|
|
{% if custom_actions %}
|
|
{% for action in custom_actions %}
|
|
<{{ action.tag|default:"button" }}
|
|
{% if action.href %}href="{{ action.href }}"{% endif %}
|
|
{% if action.onclick %}onclick="{{ action.onclick }}"{% endif %}
|
|
class="popup-btn {{ action.classes|default:'popup-btn-secondary' }}">
|
|
{% if action.icon %}<i class="mr-1 {{ action.icon }}"></i>{% endif %}{{ action.text }}
|
|
</{{ action.tag|default:"button" }}>
|
|
{% endfor %}
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Popup Styles -->
|
|
<style>
|
|
.location-popup {
|
|
max-width: 350px;
|
|
min-width: 250px;
|
|
font-family: inherit;
|
|
}
|
|
|
|
.popup-header {
|
|
margin-bottom: 0.75rem;
|
|
display: flex;
|
|
align-items: flex-start;
|
|
justify-content: space-between;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.popup-title {
|
|
margin: 0;
|
|
font-size: 1.1rem;
|
|
font-weight: 600;
|
|
color: #1f2937;
|
|
line-height: 1.3;
|
|
flex: 1;
|
|
}
|
|
|
|
.popup-type-badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
padding: 0.25rem 0.5rem;
|
|
border-radius: 9999px;
|
|
font-size: 0.75rem;
|
|
font-weight: 500;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.popup-type-park {
|
|
background-color: #dcfce7;
|
|
color: #166534;
|
|
}
|
|
|
|
.popup-type-ride {
|
|
background-color: #dbeafe;
|
|
color: #1e40af;
|
|
}
|
|
|
|
.popup-type-company {
|
|
background-color: #ede9fe;
|
|
color: #7c3aed;
|
|
}
|
|
|
|
.popup-meta {
|
|
margin: 0.375rem 0;
|
|
font-size: 0.875rem;
|
|
color: #6b7280;
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.popup-meta i {
|
|
width: 1rem;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.popup-status-badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
padding: 0.25rem 0.5rem;
|
|
border-radius: 9999px;
|
|
font-size: 0.75rem;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.popup-status-operating {
|
|
background-color: #dcfce7;
|
|
color: #166534;
|
|
}
|
|
|
|
.popup-status-closed {
|
|
background-color: #fee2e2;
|
|
color: #dc2626;
|
|
}
|
|
|
|
.popup-status-construction {
|
|
background-color: #fef3c7;
|
|
color: #d97706;
|
|
}
|
|
|
|
.popup-status-demolished {
|
|
background-color: #f3f4f6;
|
|
color: #6b7280;
|
|
}
|
|
|
|
.popup-custom {
|
|
margin: 0.75rem 0;
|
|
}
|
|
|
|
.popup-actions {
|
|
margin-top: 0.75rem;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.popup-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
padding: 0.375rem 0.75rem;
|
|
font-size: 0.875rem;
|
|
font-weight: 500;
|
|
border-radius: 0.375rem;
|
|
text-decoration: none;
|
|
border: none;
|
|
cursor: pointer;
|
|
transition: all 0.15s ease;
|
|
}
|
|
|
|
.popup-btn:hover {
|
|
transform: translateY(-1px);
|
|
}
|
|
|
|
.popup-btn-primary {
|
|
background-color: #3b82f6;
|
|
color: white;
|
|
}
|
|
|
|
.popup-btn-primary:hover {
|
|
background-color: #2563eb;
|
|
color: white;
|
|
}
|
|
|
|
.popup-btn-secondary {
|
|
background-color: #f3f4f6;
|
|
color: #374151;
|
|
border: 1px solid #d1d5db;
|
|
}
|
|
|
|
.popup-btn-secondary:hover {
|
|
background-color: #e5e7eb;
|
|
color: #374151;
|
|
}
|
|
|
|
.popup-btn-accent {
|
|
background-color: #10b981;
|
|
color: white;
|
|
}
|
|
|
|
.popup-btn-accent:hover {
|
|
background-color: #059669;
|
|
color: white;
|
|
}
|
|
|
|
/* Dark mode support */
|
|
@media (prefers-color-scheme: dark) {
|
|
.popup-title {
|
|
color: #f9fafb;
|
|
}
|
|
|
|
.popup-meta {
|
|
color: #d1d5db;
|
|
}
|
|
|
|
.popup-type-park {
|
|
background-color: #166534;
|
|
color: #dcfce7;
|
|
}
|
|
|
|
.popup-type-ride {
|
|
background-color: #1e40af;
|
|
color: #dbeafe;
|
|
}
|
|
|
|
.popup-type-company {
|
|
background-color: #7c3aed;
|
|
color: #ede9fe;
|
|
}
|
|
|
|
.popup-status-operating {
|
|
background-color: #166534;
|
|
color: #dcfce7;
|
|
}
|
|
|
|
.popup-status-closed {
|
|
background-color: #dc2626;
|
|
color: #fee2e2;
|
|
}
|
|
|
|
.popup-status-construction {
|
|
background-color: #d97706;
|
|
color: #fef3c7;
|
|
}
|
|
|
|
.popup-status-demolished {
|
|
background-color: #6b7280;
|
|
color: #f3f4f6;
|
|
}
|
|
|
|
.popup-btn-secondary {
|
|
background-color: #374151;
|
|
color: #f3f4f6;
|
|
border-color: #4b5563;
|
|
}
|
|
|
|
.popup-btn-secondary:hover {
|
|
background-color: #4b5563;
|
|
color: #f3f4f6;
|
|
}
|
|
}
|
|
|
|
/* Responsive adjustments */
|
|
@media (max-width: 480px) {
|
|
.location-popup {
|
|
max-width: 280px;
|
|
min-width: 200px;
|
|
}
|
|
|
|
.popup-actions {
|
|
flex-direction: column;
|
|
}
|
|
|
|
.popup-btn {
|
|
justify-content: center;
|
|
width: 100%;
|
|
}
|
|
}
|
|
</style>
|
|
|
|
<!-- Popup JavaScript Functions -->
|
|
<script>
|
|
// Global functions for popup actions
|
|
window.getDirections = function(lat, lng) {
|
|
// Open directions in user's preferred map app
|
|
const isMobile = /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
|
|
|
if (isMobile) {
|
|
// Try to open in native maps app
|
|
window.open(`geo:${lat},${lng}`, '_blank');
|
|
} else {
|
|
// Open in Google Maps
|
|
window.open(`https://www.google.com/maps/dir/?api=1&destination=${lat},${lng}`, '_blank');
|
|
}
|
|
};
|
|
|
|
window.addLocationToTrip = function(locationData) {
|
|
// Emit custom event for trip integration
|
|
const event = new CustomEvent('addLocationToTrip', {
|
|
detail: locationData
|
|
});
|
|
document.dispatchEvent(event);
|
|
|
|
// Show feedback
|
|
showPopupFeedback('Added to trip!', 'success');
|
|
};
|
|
|
|
window.shareLocation = function(type, id) {
|
|
// Share location URL
|
|
const url = window.location.origin + `/{{ type }}/${id}/`;
|
|
|
|
if (navigator.share) {
|
|
navigator.share({
|
|
title: 'Check out this location on ThrillWiki',
|
|
url: url
|
|
});
|
|
} else {
|
|
// Fallback: copy to clipboard
|
|
navigator.clipboard.writeText(url).then(() => {
|
|
showPopupFeedback('Link copied to clipboard!', 'success');
|
|
}).catch(() => {
|
|
showPopupFeedback('Could not copy link', 'error');
|
|
});
|
|
}
|
|
};
|
|
|
|
window.showPopupFeedback = function(message, type = 'info') {
|
|
// Create temporary feedback element
|
|
const feedback = document.createElement('div');
|
|
feedback.className = `popup-feedback popup-feedback-${type}`;
|
|
feedback.textContent = message;
|
|
feedback.style.cssText = `
|
|
position: fixed;
|
|
top: 20px;
|
|
right: 20px;
|
|
background: ${type === 'success' ? '#10b981' : type === 'error' ? '#ef4444' : '#3b82f6'};
|
|
color: white;
|
|
padding: 0.75rem 1rem;
|
|
border-radius: 0.5rem;
|
|
font-size: 0.875rem;
|
|
font-weight: 500;
|
|
z-index: 10000;
|
|
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
|
|
animation: slideIn 0.3s ease;
|
|
`;
|
|
|
|
document.body.appendChild(feedback);
|
|
|
|
// Remove after 3 seconds
|
|
setTimeout(() => {
|
|
feedback.style.animation = 'slideOut 0.3s ease';
|
|
setTimeout(() => {
|
|
document.body.removeChild(feedback);
|
|
}, 300);
|
|
}, 3000);
|
|
};
|
|
|
|
// Add CSS animations
|
|
if (!document.getElementById('popup-animations')) {
|
|
const style = document.createElement('style');
|
|
style.id = 'popup-animations';
|
|
style.textContent = `
|
|
@keyframes slideIn {
|
|
from { transform: translateX(100%); opacity: 0; }
|
|
to { transform: translateX(0); opacity: 1; }
|
|
}
|
|
|
|
@keyframes slideOut {
|
|
from { transform: translateX(0); opacity: 1; }
|
|
to { transform: translateX(100%); opacity: 0; }
|
|
}
|
|
`;
|
|
document.head.appendChild(style);
|
|
}
|
|
</script> |