feat: dynamic service pages with custom forms
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1050,6 +1050,178 @@ select.form-control {
|
||||
color: #0c5460;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
Service Page — Hero
|
||||
============================================================ */
|
||||
.service-hero {
|
||||
background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-dark) 50%, #0E1F30 100%);
|
||||
padding: calc(var(--navbar-height) + var(--space-3xl)) 0 var(--space-3xl);
|
||||
text-align: center;
|
||||
color: var(--color-white);
|
||||
}
|
||||
|
||||
.service-hero__icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
border-radius: 50%;
|
||||
background: rgba(201, 169, 78, 0.15);
|
||||
border: 2px solid rgba(201, 169, 78, 0.3);
|
||||
color: var(--color-accent);
|
||||
font-size: 2.2rem;
|
||||
margin-bottom: var(--space-lg);
|
||||
}
|
||||
|
||||
.service-hero h1 {
|
||||
font-size: var(--font-size-3xl);
|
||||
font-weight: 800;
|
||||
color: var(--color-white);
|
||||
margin-bottom: var(--space-md);
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
.service-hero__price {
|
||||
font-size: var(--font-size-lg);
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.service-hero__price strong {
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
.service-hero__price i {
|
||||
color: var(--color-accent);
|
||||
margin-right: var(--space-xs);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
Service Page — Detail Layout
|
||||
============================================================ */
|
||||
.service-detail {
|
||||
display: grid;
|
||||
grid-template-columns: 1.4fr 1fr;
|
||||
gap: var(--space-3xl);
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.service-detail__info {
|
||||
padding-right: var(--space-xl);
|
||||
}
|
||||
|
||||
.service-detail__desc {
|
||||
font-size: var(--font-size-md);
|
||||
color: var(--color-gray-700);
|
||||
line-height: var(--line-height-loose);
|
||||
margin-bottom: var(--space-2xl);
|
||||
}
|
||||
|
||||
.service-detail__info h2 {
|
||||
font-size: var(--font-size-xl);
|
||||
font-weight: 700;
|
||||
color: var(--color-gray-900);
|
||||
margin-bottom: var(--space-lg);
|
||||
margin-top: var(--space-2xl);
|
||||
}
|
||||
|
||||
.service-detail__info h2:first-of-type {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.service-detail__info h2 i {
|
||||
color: var(--color-accent);
|
||||
margin-right: var(--space-sm);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
Service Page — Requirements List
|
||||
============================================================ */
|
||||
.requirements-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-md);
|
||||
}
|
||||
|
||||
.requirements-list li {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: var(--space-sm);
|
||||
font-size: var(--font-size-base);
|
||||
color: var(--color-gray-700);
|
||||
line-height: var(--line-height-normal);
|
||||
}
|
||||
|
||||
.requirements-list li i {
|
||||
color: var(--color-success);
|
||||
font-size: var(--font-size-md);
|
||||
flex-shrink: 0;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
Service Page — Process Steps
|
||||
============================================================ */
|
||||
.process-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-lg);
|
||||
counter-reset: none;
|
||||
}
|
||||
|
||||
.process-list li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-md);
|
||||
font-size: var(--font-size-base);
|
||||
color: var(--color-gray-700);
|
||||
line-height: var(--line-height-normal);
|
||||
}
|
||||
|
||||
.step-number {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, var(--color-primary), var(--color-primary-light));
|
||||
color: var(--color-white);
|
||||
font-size: var(--font-size-sm);
|
||||
font-weight: 700;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
Service Page — Form Card
|
||||
============================================================ */
|
||||
.service-detail__form {
|
||||
background-color: var(--color-white);
|
||||
border: 1px solid var(--color-gray-200);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: var(--space-2xl);
|
||||
box-shadow: var(--shadow-md);
|
||||
position: sticky;
|
||||
top: calc(var(--navbar-height) + var(--space-lg));
|
||||
}
|
||||
|
||||
.service-detail__form h2 {
|
||||
font-size: var(--font-size-xl);
|
||||
font-weight: 700;
|
||||
color: var(--color-gray-900);
|
||||
margin-bottom: var(--space-xl);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.service-detail__form label {
|
||||
display: block;
|
||||
font-size: var(--font-size-sm);
|
||||
font-weight: 600;
|
||||
color: var(--color-gray-800);
|
||||
margin-bottom: var(--space-xs);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
Scroll Animations
|
||||
============================================================ */
|
||||
@@ -1218,6 +1390,24 @@ select.form-control {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
/* Service page */
|
||||
.service-hero h1 {
|
||||
font-size: var(--font-size-2xl);
|
||||
}
|
||||
|
||||
.service-detail {
|
||||
grid-template-columns: 1fr;
|
||||
gap: var(--space-2xl);
|
||||
}
|
||||
|
||||
.service-detail__info {
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.service-detail__form {
|
||||
position: static;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
.footer__grid {
|
||||
grid-template-columns: 1fr;
|
||||
@@ -1258,6 +1448,25 @@ select.form-control {
|
||||
padding: 0.75rem 1.5rem;
|
||||
font-size: var(--font-size-base);
|
||||
}
|
||||
|
||||
/* Service page small mobile */
|
||||
.service-hero {
|
||||
padding: calc(var(--navbar-height) + var(--space-2xl)) var(--space-md) var(--space-2xl);
|
||||
}
|
||||
|
||||
.service-hero__icon {
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
.service-hero h1 {
|
||||
font-size: var(--font-size-xl);
|
||||
}
|
||||
|
||||
.service-detail__form {
|
||||
padding: var(--space-xl) var(--space-lg);
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
|
||||
114
servicio.php
Normal file
114
servicio.php
Normal file
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/includes/servicios-data.php';
|
||||
require_once __DIR__ . '/includes/csrf.php';
|
||||
|
||||
$slug = $_GET['s'] ?? '';
|
||||
if (!isset($SERVICIOS[$slug])) {
|
||||
http_response_code(404);
|
||||
$pageTitle = 'Servicio no encontrado';
|
||||
require_once __DIR__ . '/includes/header.php';
|
||||
echo '<section class="section" style="text-align:center;padding:100px 20px;">'
|
||||
. '<h1>Servicio no encontrado</h1>'
|
||||
. '<p>El servicio solicitado no existe.</p>'
|
||||
. '<a href="index.php" class="btn btn--primary">Volver al inicio</a>'
|
||||
. '</section>';
|
||||
require_once __DIR__ . '/includes/footer.php';
|
||||
exit;
|
||||
}
|
||||
|
||||
$servicio = $SERVICIOS[$slug];
|
||||
$pageTitle = $servicio['nombre'] . ' - Gestoría LP';
|
||||
|
||||
if (session_status() === PHP_SESSION_NONE) session_start();
|
||||
|
||||
require_once __DIR__ . '/includes/header.php';
|
||||
?>
|
||||
|
||||
<!-- Service Hero -->
|
||||
<section class="service-hero">
|
||||
<div class="container">
|
||||
<div class="service-hero__icon">
|
||||
<i class="fas <?= htmlspecialchars($servicio['icono']) ?>"></i>
|
||||
</div>
|
||||
<h1><?= htmlspecialchars($servicio['nombre']) ?></h1>
|
||||
<p class="service-hero__price"><i class="fas fa-tag"></i> Precio: <strong><?= htmlspecialchars($servicio['precio']) ?></strong></p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Service Detail -->
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
<div class="service-detail">
|
||||
<div class="service-detail__info">
|
||||
<p class="service-detail__desc"><?= htmlspecialchars($servicio['descripcion']) ?></p>
|
||||
|
||||
<h2><i class="fas fa-clipboard-list"></i> Requisitos</h2>
|
||||
<ul class="requirements-list">
|
||||
<?php foreach ($servicio['requisitos'] as $req): ?>
|
||||
<li><i class="fas fa-check-circle"></i> <?= htmlspecialchars($req) ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
|
||||
<h2><i class="fas fa-tasks"></i> Proceso</h2>
|
||||
<ol class="process-list">
|
||||
<?php foreach ($servicio['proceso'] as $i => $paso): ?>
|
||||
<li>
|
||||
<span class="step-number"><?= $i + 1 ?></span>
|
||||
<?= htmlspecialchars($paso) ?>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div class="service-detail__form" id="formulario">
|
||||
<h2>Solicita este tramite</h2>
|
||||
<form action="formulario.php" method="POST">
|
||||
<?= csrfField() ?>
|
||||
<input type="hidden" name="servicio" value="<?= htmlspecialchars($slug) ?>">
|
||||
|
||||
<div class="form-group">
|
||||
<label for="nombre">Nombre completo *</label>
|
||||
<input type="text" id="nombre" name="nombre" class="form-control" required placeholder="Tu nombre completo">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="telefono">Telefono *</label>
|
||||
<input type="tel" id="telefono" name="telefono" class="form-control" required placeholder="Ej: 612 123 4567">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email">Correo electronico</label>
|
||||
<input type="email" id="email" name="email" class="form-control" placeholder="tucorreo@ejemplo.com">
|
||||
</div>
|
||||
|
||||
<?php foreach ($servicio['campos_formulario'] as $campo): ?>
|
||||
<div class="form-group">
|
||||
<label for="<?= htmlspecialchars($campo['name']) ?>">
|
||||
<?= htmlspecialchars($campo['label']) ?>
|
||||
<?= $campo['required'] ? ' *' : '' ?>
|
||||
</label>
|
||||
<?php if ($campo['type'] === 'select'): ?>
|
||||
<select id="<?= htmlspecialchars($campo['name']) ?>" name="<?= htmlspecialchars($campo['name']) ?>" class="form-control" <?= $campo['required'] ? 'required' : '' ?>>
|
||||
<option value="">Seleccione...</option>
|
||||
<?php foreach ($campo['options'] as $opt): ?>
|
||||
<option value="<?= htmlspecialchars($opt) ?>"><?= htmlspecialchars($opt) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<?php elseif ($campo['type'] === 'textarea'): ?>
|
||||
<textarea id="<?= htmlspecialchars($campo['name']) ?>" name="<?= htmlspecialchars($campo['name']) ?>" class="form-control" rows="4" <?= $campo['required'] ? 'required' : '' ?> placeholder="Escribe aqui..."></textarea>
|
||||
<?php elseif ($campo['type'] === 'date'): ?>
|
||||
<input type="date" id="<?= htmlspecialchars($campo['name']) ?>" name="<?= htmlspecialchars($campo['name']) ?>" class="form-control" <?= $campo['required'] ? 'required' : '' ?>>
|
||||
<?php else: ?>
|
||||
<input type="text" id="<?= htmlspecialchars($campo['name']) ?>" name="<?= htmlspecialchars($campo['name']) ?>" class="form-control" <?= $campo['required'] ? 'required' : '' ?>>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<button type="submit" class="btn btn--primary btn--block">
|
||||
<i class="fas fa-paper-plane"></i> Solicitar <?= htmlspecialchars($servicio['nombre']) ?>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
||||
Reference in New Issue
Block a user