276 lines
12 KiB
PHP
276 lines
12 KiB
PHP
@extends('layouts.app')
|
|
|
|
@section('title', 'Lugares - OnAPB')
|
|
|
|
@section('styles')
|
|
<link rel="stylesheet" href="{{ asset('static/lugares.css?v=5') }}">
|
|
@endsection
|
|
|
|
@section('content')
|
|
<div class="container-fluid py-5" style="background: var(--surface);">
|
|
<div class="container py-4">
|
|
<div class="mb-5">
|
|
<span class="text-primary fw-bold tracking-widest text-uppercase d-block mb-2">Comunidad</span>
|
|
<h1 class="display-1 fw-bold mb-3" style="line-height: 0.9;">Lugares de Interés</h1>
|
|
<div style="width: 150px; height: 10px; background: var(--primary);"></div>
|
|
</div>
|
|
|
|
<!-- Filters Editorial -->
|
|
<div class="bg-white p-5 mb-5 shadow-sm" style="border-left: 10px solid var(--primary-container);">
|
|
<div class="row g-4 align-items-end">
|
|
<div class="col-md-5">
|
|
<label class="small fw-bold text-uppercase text-muted mb-2 d-block">Búsqueda</label>
|
|
<input type="text" id="searchFilter" class="form-control form-control-lg border-0 bg-light p-3" placeholder="Club, comercio, etc..." oninput="filterPromos()" style="border-radius: 0;">
|
|
</div>
|
|
<div class="col-md-5">
|
|
<label class="small fw-bold text-uppercase text-muted mb-2 d-block">Categoría</label>
|
|
<select id="categoryFilter" class="form-select form-select-lg border-0 bg-light p-3" onchange="filterPromos()" style="border-radius: 0;">
|
|
<option value="">Todas</option>
|
|
@foreach($categorias as $cat)
|
|
<option value="{{ strtolower($cat) }}">{{ ucfirst($cat) }}</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
<div class="col-md-2">
|
|
<button class="btn-kinetic-primary w-100 py-3" onclick="filterPromos()">FILTRAR</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Promo Grid -->
|
|
<div id="promo-grid" class="row g-4">
|
|
@forelse($promociones as $p)
|
|
<div class="col-md-4 promo-card" data-categoria="{{ strtolower($p->categoria ?? '') }}" data-nombre="{{ strtolower($p->nombre) }}">
|
|
<div class="kinetic-card p-0 h-100 overflow-hidden d-flex flex-column" onclick="showPromoDetail({{ $p->id }})" style="cursor: pointer; border-radius: 0;">
|
|
@if($p->imagen)
|
|
<div style="height: 250px; overflow: hidden; position: relative;">
|
|
<img src="{{ asset('storage/' . $p->imagen) }}" class="w-100 h-100" style="object-fit: cover;" alt="{{ $p->nombre }}">
|
|
<div class="position-absolute bottom-0 start-0 bg-primary text-white px-3 py-1 small fw-bold text-uppercase">{{ $p->categoria }}</div>
|
|
</div>
|
|
@endif
|
|
<div class="p-4 flex-grow-1">
|
|
<h4 class="h3 fw-bold mb-3">{{ $p->nombre }}</h4>
|
|
<p class="text-muted small mb-4">{{ Str::limit($p->descripcion_lugar ?? $p->descripcion, 100) }}</p>
|
|
|
|
@if($p->descripcion && trim($p->descripcion))
|
|
<span class="text-primary small fw-bold"><i class="bi bi-star-fill"></i> BENEFICIO ACTIVO</span>
|
|
@endif
|
|
<p class="small text-muted mb-0 mt-3"><i class="bi bi-geo-alt"></i> {{ $p->direccion }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@empty
|
|
<div class="col-12 text-center py-5">
|
|
<div class="kinetic-card p-5">
|
|
<i class="bi bi-geo text-muted mb-3" style="font-size: 3rem;"></i>
|
|
<p class="fs-4 text-muted">No se encontraron lugares.</p>
|
|
</div>
|
|
</div>
|
|
@endforelse
|
|
</div>
|
|
|
|
<!-- Detail Modal Redux (Inline) -->
|
|
<div id="promo-detail" class="bg-white shadow-lg p-5 my-5" style="display: none; border: 2px solid var(--primary-container);">
|
|
<div class="row g-5 align-items-center">
|
|
<div class="col-md-5">
|
|
<img id="detail-img" src="" class="w-100 shadow-sm" style="height: 350px; object-fit: cover;" alt="Promo detail">
|
|
</div>
|
|
<div class="col-md-7">
|
|
<div class="d-flex justify-content-between align-items-start mb-3">
|
|
<div>
|
|
<span id="detail-categoria" class="badge bg-primary text-uppercase mb-2"></span>
|
|
<h2 id="detail-nombre" class="display-3 fw-bold mb-0"></h2>
|
|
</div>
|
|
<button class="btn-close" onclick="closeDetail()"></button>
|
|
</div>
|
|
<p id="detail-descripcion" class="fs-5 text-muted mb-4"></p>
|
|
<p class="fs-5 mb-4"><i class="bi bi-geo-alt-fill text-primary"></i> <span id="detail-direccion"></span></p>
|
|
|
|
<div id="detail-promo" class="p-4 bg-light mb-4 border-start border-primary border-5" style="display: none;">
|
|
<h5 class="fw-bold text-primary mb-2">Beneficio para Asociados:</h5>
|
|
<p id="detail-promo-text" class="fs-5 mb-0 fw-bold"></p>
|
|
</div>
|
|
|
|
<div class="d-flex gap-3 mt-4">
|
|
<div id="detail-actions"></div>
|
|
<button class="btn btn-dark btn-lg px-4" onclick="ubicarEnMapa()" style="border-radius: 0;">VER MAPA</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
@if(session('admin_logged_in'))
|
|
<div class="text-center mt-5">
|
|
<a href="{{ route('admin.promociones.index') }}" class="btn-kinetic-primary px-5 py-3">ADMINISTRAR LUGARES</a>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Mapa -->
|
|
<div class="container-fluid mt-4 px-0">
|
|
<div id="map" style="height: 400px;"></div>
|
|
</div>
|
|
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css"/>
|
|
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
|
|
<script src="https://unpkg.com/leaflet.markercluster/dist/leaflet.markercluster.js"></script>
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster/dist/MarkerCluster.css" />
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster/dist/MarkerCluster.Default.css" />
|
|
|
|
<script>
|
|
const promos = @json($promociones);
|
|
let map;
|
|
let markers = {};
|
|
let markersCluster;
|
|
let selectedPromoId = null;
|
|
|
|
function formatCategoria(c) {
|
|
if (!c) return "Sin categoría";
|
|
return c.charAt(0).toUpperCase() + c.slice(1).toLowerCase();
|
|
}
|
|
|
|
function getIcon(categoria) {
|
|
const colors = {
|
|
'clubes': '#e74c3c',
|
|
'comida': '#f39c12',
|
|
'salud': '#27ae60',
|
|
'vestimenta_y_estilo': '#9b59b6',
|
|
'calzado_deportivo': '#3498db',
|
|
'entretenimiento': '#1abc9c',
|
|
'hospedaje': '#34495e'
|
|
};
|
|
const color = colors[categoria?.toLowerCase()] || '#95a5a6';
|
|
|
|
return L.divIcon({
|
|
className: 'custom-marker',
|
|
html: `<div style="background:${color};width:30px;height:30px;border-radius:50%;border:3px solid white;box-shadow:0 2px 5px rgba(0,0,0,0.3);"></div>`,
|
|
iconSize: [30, 30],
|
|
iconAnchor: [15, 15]
|
|
});
|
|
}
|
|
|
|
function initMap() {
|
|
map = L.map('map').setView([-31.744, -60.53], 13);
|
|
|
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
|
attribution: '© OpenStreetMap'
|
|
}).addTo(map);
|
|
|
|
markersCluster = L.markerClusterGroup({
|
|
disableClusteringAtZoom: 13,
|
|
spiderfyOnMaxZoom: true,
|
|
showCoverageOnHover: false,
|
|
maxClusterRadius: 50
|
|
});
|
|
|
|
promos.forEach(p => {
|
|
if (p.lat && p.lng) {
|
|
const marker = L.marker([p.lat, p.lng], { icon: getIcon(p.categoria) });
|
|
const popupContent = `
|
|
<strong>${p.nombre}</strong><br>
|
|
<small>${p.direccion || ''}</small><br>
|
|
<small>${p.descripcion_lugar || p.descripcion || ''}</small><br>
|
|
<a href="javascript:void(0)" onclick="event.preventDefault(); showPromoDetail(${p.id});">Ver detalle</a>
|
|
`;
|
|
marker.bindPopup(popupContent);
|
|
markersCluster.addLayer(marker);
|
|
markers[p.id] = marker;
|
|
}
|
|
});
|
|
|
|
map.addLayer(markersCluster);
|
|
}
|
|
|
|
function filterPromos() {
|
|
const search = document.getElementById('searchFilter').value.toLowerCase().trim();
|
|
const cat = document.getElementById('categoryFilter').value;
|
|
|
|
document.querySelectorAll('.promo-card').forEach(card => {
|
|
const nombre = card.dataset.nombre;
|
|
const categoria = card.dataset.categoria;
|
|
|
|
const matchSearch = !search || nombre.includes(search);
|
|
const matchCat = !cat || categoria === cat;
|
|
|
|
card.style.display = (matchSearch && matchCat) ? 'block' : 'none';
|
|
});
|
|
}
|
|
|
|
function showPromoDetail(id) {
|
|
const p = promos.find(x => x.id === id);
|
|
if (!p) return;
|
|
|
|
selectedPromoId = id;
|
|
|
|
document.getElementById('detail-img').src = p.imagen ? '/storage/' + p.imagen : '';
|
|
document.getElementById('detail-nombre').textContent = p.nombre;
|
|
document.getElementById('detail-categoria').innerHTML = '<span class="badge bg-secondary">' + formatCategoria(p.categoria) + '</span>';
|
|
document.getElementById('detail-descripcion').textContent = p.descripcion_lugar || '';
|
|
document.getElementById('detail-direccion').textContent = p.direccion || '';
|
|
|
|
if (p.descripcion && p.descripcion.trim()) {
|
|
document.getElementById('detail-promo').style.display = 'block';
|
|
document.getElementById('detail-promo-text').textContent = p.descripcion;
|
|
} else {
|
|
document.getElementById('detail-promo').style.display = 'none';
|
|
}
|
|
|
|
// Mostrar botón solo si tiene beneficio y está logueado
|
|
const actionsDiv = document.getElementById('detail-actions');
|
|
@if(session('user_logged_in'))
|
|
if (p.descripcion && p.descripcion.trim()) {
|
|
actionsDiv.innerHTML = '<form method="POST" action="{{ route('panel.generar.promo.qr') }}" class="d-inline confirm-submit" data-confirm-text="¿Generar QR de beneficio?" data-confirm-button="Generar QR" data-confirm-icon="question"><input type="hidden" name="_token" value="{{ csrf_token() }}"><input type="hidden" name="id_promo" value="' + id + '"><button type="submit" class="btn btn-success">🎟️ Solicitar beneficio</button></form>';
|
|
} else {
|
|
actionsDiv.innerHTML = '';
|
|
}
|
|
@else
|
|
if (p.descripcion && p.descripcion.trim()) {
|
|
actionsDiv.innerHTML = '<button class="btn btn-outline-primary" data-bs-toggle="modal" data-bs-target="#loginModal">Iniciá sesión para el beneficio</button>';
|
|
} else {
|
|
actionsDiv.innerHTML = '';
|
|
}
|
|
@endif
|
|
|
|
document.getElementById('promo-detail').style.display = 'block';
|
|
|
|
// Scroll hacia el detalle
|
|
document.getElementById('promo-detail').scrollIntoView({ behavior: 'smooth' });
|
|
|
|
// Auto-ubicar en el mapa
|
|
if (p.lat && p.lng) {
|
|
map.setView([p.lat, p.lng], 16);
|
|
if (markers[id]) {
|
|
markers[id].openPopup();
|
|
}
|
|
}
|
|
}
|
|
|
|
function ubicarEnMapa() {
|
|
if (selectedPromoId && markers[selectedPromoId]) {
|
|
const p = promos.find(x => x.id === selectedPromoId);
|
|
if (p && p.lat && p.lng) {
|
|
map.setView([p.lat, p.lng], 16);
|
|
markers[selectedPromoId].openPopup();
|
|
document.getElementById('map').scrollIntoView({ behavior: 'smooth' });
|
|
}
|
|
}
|
|
}
|
|
|
|
function closeDetail() {
|
|
document.getElementById('promo-detail').style.display = 'none';
|
|
selectedPromoId = null;
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
initMap();
|
|
});
|
|
</script>
|
|
|
|
<style>
|
|
.custom-marker { background: transparent; border: none; }
|
|
.promo-clickable { cursor: pointer; transition: transform 0.2s; }
|
|
.promo-clickable:hover { transform: scale(1.02); }
|
|
</style>
|
|
@endsection
|