150 lines
7.1 KiB
PHP
150 lines
7.1 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
require_once __DIR__ . '/../includes/taxilanz.php';
|
|
app_boot();
|
|
|
|
$rideUuid = trim((string) ($_GET['ride'] ?? ''));
|
|
$ride = $rideUuid !== '' ? find_ride_by_uuid($rideUuid) : null;
|
|
|
|
if (!$ride) {
|
|
http_response_code(404);
|
|
render_page_start('Solicitud no encontrada', 'No se encontro la solicitud de taxi solicitada.', 'home');
|
|
?>
|
|
<section class="card-shell p-5 text-center">
|
|
<div class="empty-state">
|
|
<strong>No encontramos esa solicitud.</strong>
|
|
<p class="text-secondary mb-4">Puede que la referencia no exista o que la demo se haya reiniciado.</p>
|
|
<a class="btn btn-app-primary" href="/">Volver al inicio</a>
|
|
</div>
|
|
</section>
|
|
<?php
|
|
render_page_end();
|
|
exit;
|
|
}
|
|
|
|
$recommendations = recommendations_for_ride($ride, 3);
|
|
log_recommendation_views($ride, $recommendations);
|
|
|
|
render_page_start(
|
|
'Taxi confirmado',
|
|
'Tu taxi ya esta confirmado y TaxiLanz te propone experiencias y servicios relevantes mientras esperas.',
|
|
'home'
|
|
);
|
|
?>
|
|
<section class="row g-4 mb-4">
|
|
<div class="col-12 col-lg-5">
|
|
<div class="card-shell p-4 p-lg-5 h-100">
|
|
<div class="section-head mb-4">
|
|
<div>
|
|
<div class="eyebrow">Estado del ride</div>
|
|
<h1 class="section-title mb-1">Taxi confirmado</h1>
|
|
<p class="text-secondary mb-0">Referencia <?= h($ride['uuid']) ?></p>
|
|
</div>
|
|
<span class="status-badge success">ETA <?= h((string) $ride['eta_minutes']) ?> min</span>
|
|
</div>
|
|
<div class="summary-block mb-4">
|
|
<div class="summary-line">
|
|
<span>Origen</span>
|
|
<strong><?= h($ride['pickup_label']) ?></strong>
|
|
</div>
|
|
<div class="summary-line">
|
|
<span>Destino</span>
|
|
<strong><?= h($ride['destination_label']) ?></strong>
|
|
</div>
|
|
<div class="summary-line">
|
|
<span>Salida</span>
|
|
<strong><?= h(format_datetime($ride['scheduled_for'])) ?></strong>
|
|
</div>
|
|
<div class="summary-line">
|
|
<span>Canal</span>
|
|
<strong><?= h(strtoupper((string) $ride['source_channel'])) ?></strong>
|
|
</div>
|
|
</div>
|
|
<div class="notice-panel mb-4">
|
|
<strong>Mientras esperas</strong>
|
|
<p class="mb-0 text-secondary">El motor simple prioriza offers publicadas segun zona, categoria y prioridad operativa. Este es el momento clave de conversión del MVP.</p>
|
|
</div>
|
|
<div class="d-flex flex-column flex-sm-row gap-2">
|
|
<a class="btn btn-app-primary" href="#recommendations">Ver recomendaciones</a>
|
|
<a class="btn btn-app-secondary" href="/operations/">Ir a operaciones</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-12 col-lg-7">
|
|
<div class="card-shell p-4 p-lg-5 h-100">
|
|
<div class="section-head mb-4">
|
|
<div>
|
|
<div class="eyebrow">Señales usadas</div>
|
|
<h2 class="section-title mb-1">Por que estas ofertas</h2>
|
|
<p class="text-secondary mb-0">El primer MVP evita IA y usa reglas simples para mantenerse rapido, visible y facil de depurar.</p>
|
|
</div>
|
|
</div>
|
|
<div class="row g-3">
|
|
<div class="col-12 col-md-6">
|
|
<div class="detail-card h-100">
|
|
<span class="detail-kicker">Contexto</span>
|
|
<strong><?= h($ride['context_zone'] ?? 'general') ?></strong>
|
|
<p class="text-secondary mb-0">Inferido a partir del origen y el destino de la solicitud.</p>
|
|
</div>
|
|
</div>
|
|
<div class="col-12 col-md-6">
|
|
<div class="detail-card h-100">
|
|
<span class="detail-kicker">Idioma</span>
|
|
<strong><?= h($ride['locale'] ?? 'es-ES') ?></strong>
|
|
<p class="text-secondary mb-0">Se conserva como metadato util para personalizacion futura.</p>
|
|
</div>
|
|
</div>
|
|
<div class="col-12 col-md-6">
|
|
<div class="detail-card h-100">
|
|
<span class="detail-kicker">Prioridad</span>
|
|
<strong>Featured + score</strong>
|
|
<p class="text-secondary mb-0">Las offers destacadas y disponibles ahora reciben empuje adicional.</p>
|
|
</div>
|
|
</div>
|
|
<div class="col-12 col-md-6">
|
|
<div class="detail-card h-100">
|
|
<span class="detail-kicker">Tracking</span>
|
|
<strong>Eventos activos</strong>
|
|
<p class="text-secondary mb-0">Ya registramos solicitud creada y vistas de recomendacion para analisis basico.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="card-shell p-4 p-lg-5" id="recommendations">
|
|
<div class="section-head mb-4">
|
|
<div>
|
|
<div class="eyebrow">Top 3 recomendado</div>
|
|
<h2 class="section-title mb-1">Mientras llega tu taxi...</h2>
|
|
<p class="text-secondary mb-0">Estas cards enlazan al detalle y al formulario de reserva. Ese paso ya guarda booking y eventos reales.</p>
|
|
</div>
|
|
<span class="status-badge">Conversión</span>
|
|
</div>
|
|
<div class="row g-3">
|
|
<?php foreach ($recommendations as $offer): ?>
|
|
<div class="col-12 col-xl-4">
|
|
<article class="offer-card h-100 emphasis">
|
|
<img src="<?= h($offer['image_url']) ?>" class="offer-image" alt="<?= h($offer['title']) ?>" loading="lazy" width="640" height="420">
|
|
<div class="offer-body">
|
|
<div class="offer-meta">
|
|
<span class="chip"><?= h(category_label($offer['category'])) ?></span>
|
|
<span class="text-secondary small">Score <?= h((string) $offer['recommendation_score']) ?></span>
|
|
</div>
|
|
<h3 class="offer-title"><?= h($offer['title']) ?></h3>
|
|
<p class="offer-text"><?= h(excerpt_for_offer($offer)) ?></p>
|
|
<div class="summary-block slim mb-3">
|
|
<div class="summary-line"><span>Ubicacion</span><strong><?= h($offer['location_label'] ?? 'Lanzarote') ?></strong></div>
|
|
<div class="summary-line"><span>Desde</span><strong><?= h(format_currency($offer['price_from'])) ?></strong></div>
|
|
</div>
|
|
<a class="btn btn-app-primary w-100" href="/offers/?slug=<?= urlencode($offer['slug']) ?>&ride=<?= urlencode($ride['uuid']) ?>">Ver detalle y reservar</a>
|
|
</div>
|
|
</article>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</section>
|
|
<?php render_page_end(); ?>
|