feat: integrar campos WhatsForm en formulario de visa
Reemplaza los 4 campos básicos del formulario de visa con 40+ campos del DS-160 organizados en 7 secciones (datos personales, patrocinador, historial migratorio, dirección, datos familiares, empleo, estudios). Agrega soporte para tipos heading (divisor de sección) y radio buttons. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1104,6 +1104,39 @@ select.form-control {
|
||||
padding-right: 2.5rem;
|
||||
}
|
||||
|
||||
.form-heading {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-accent);
|
||||
margin-top: var(--space-lg);
|
||||
margin-bottom: var(--space-md);
|
||||
padding-bottom: var(--space-xs);
|
||||
border-bottom: 1px solid rgba(192, 192, 192, 0.2);
|
||||
}
|
||||
|
||||
.form-radio-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--space-sm) var(--space-md);
|
||||
padding-top: var(--space-xs);
|
||||
}
|
||||
|
||||
.form-radio-label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
font-size: var(--font-size-sm);
|
||||
color: var(--color-gray-700);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.form-radio-label input[type="radio"] {
|
||||
accent-color: var(--color-accent);
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.form-error {
|
||||
font-size: var(--font-size-xs);
|
||||
color: var(--color-danger);
|
||||
|
||||
@@ -30,8 +30,9 @@ if (!$nombre || !$telefono || !isset($SERVICIOS[$servicio])) {
|
||||
// Collect service-specific fields
|
||||
$datosExtra = [];
|
||||
foreach ($SERVICIOS[$servicio]['campos_formulario'] as $campo) {
|
||||
if (empty($campo['name'])) continue; // Skip headings
|
||||
$val = trim($_POST[$campo['name']] ?? '');
|
||||
if ($campo['required'] && !$val) {
|
||||
if (!empty($campo['required']) && !$val) {
|
||||
die('Por favor llene el campo: ' . htmlspecialchars($campo['label']));
|
||||
}
|
||||
$datosExtra[$campo['label']] = $val;
|
||||
|
||||
@@ -20,9 +20,69 @@ $SERVICIOS = [
|
||||
'Acompañamiento el día de la cita',
|
||||
],
|
||||
'campos_formulario' => [
|
||||
// Tipo de trámite
|
||||
['name' => 'tipo_visa', 'label' => 'Tipo de visa', 'type' => 'select', 'options' => ['Turista (B1/B2)', 'Estudiante (F1)', 'Trabajo (H1B)', 'Otro'], 'required' => true],
|
||||
['name' => 'primera_vez', 'label' => '¿Es primera vez o renovación?', 'type' => 'select', 'options' => ['Primera vez', 'Renovación'], 'required' => true],
|
||||
['name' => 'pasaporte_vigente', 'label' => '¿Tiene pasaporte vigente?', 'type' => 'select', 'options' => ['Sí', 'No'], 'required' => true],
|
||||
|
||||
// Datos personales
|
||||
['type' => 'heading', 'label' => 'Datos personales'],
|
||||
['name' => 'fecha_nacimiento', 'label' => 'Fecha de nacimiento', 'type' => 'date', 'required' => true],
|
||||
['name' => 'lugar_nacimiento', 'label' => 'Lugar de nacimiento', 'type' => 'text', 'required' => true],
|
||||
['name' => 'curp', 'label' => 'CURP', 'type' => 'text', 'required' => true],
|
||||
['name' => 'estado_civil', 'label' => 'Estado civil', 'type' => 'radio', 'options' => ['Casado', 'Soltero', 'Viudo', 'Unión libre'], 'required' => false],
|
||||
['name' => 'nombre_pareja', 'label' => 'Nombre completo de la pareja', 'type' => 'text', 'required' => false],
|
||||
['name' => 'lugar_fecha_nacimiento_pareja', 'label' => 'Lugar y fecha de nacimiento de la pareja', 'type' => 'text', 'required' => false],
|
||||
|
||||
// Patrocinador del viaje
|
||||
['type' => 'heading', 'label' => 'Patrocinador del viaje'],
|
||||
['name' => 'quien_paga_viaje', 'label' => '¿Quién paga el viaje?', 'type' => 'text', 'required' => false],
|
||||
['name' => 'nombre_patrocinador', 'label' => 'Nombre del patrocinador', 'type' => 'text', 'required' => false],
|
||||
['name' => 'parentesco_patrocinador', 'label' => 'Parentesco con el patrocinador', 'type' => 'text', 'required' => false],
|
||||
['name' => 'telefono_patrocinador', 'label' => 'Teléfono del patrocinador', 'type' => 'text', 'required' => false],
|
||||
['name' => 'email_patrocinador', 'label' => 'Email del patrocinador', 'type' => 'text', 'required' => false],
|
||||
|
||||
// Historial migratorio
|
||||
['type' => 'heading', 'label' => 'Historial migratorio'],
|
||||
['name' => 'ultimos_cruces', 'label' => 'Liste sus últimos 5 cruces a EE.UU. (fechas y motivo)', 'type' => 'textarea', 'required' => false],
|
||||
['name' => 'visa_perdida_robada', 'label' => '¿Ha perdido o le han robado una visa?', 'type' => 'select', 'options' => ['Sí', 'No'], 'required' => false],
|
||||
['name' => 'anio_perdida', 'label' => 'Año de la pérdida/robo', 'type' => 'text', 'required' => false],
|
||||
['name' => 'como_fue_perdida', 'label' => '¿Cómo fue la pérdida/robo?', 'type' => 'textarea', 'required' => false],
|
||||
['name' => 'visa_negada', 'label' => '¿Le han negado una visa anteriormente?', 'type' => 'select', 'options' => ['Sí', 'No'], 'required' => false],
|
||||
['name' => 'peticion_migracion', 'label' => '¿Tiene alguna petición de migración en proceso?', 'type' => 'select', 'options' => ['Sí', 'No'], 'required' => false],
|
||||
|
||||
// Dirección personal
|
||||
['type' => 'heading', 'label' => 'Dirección personal'],
|
||||
['name' => 'direccion', 'label' => 'Dirección completa', 'type' => 'text', 'required' => true],
|
||||
|
||||
// Datos familiares
|
||||
['type' => 'heading', 'label' => 'Datos familiares'],
|
||||
['name' => 'nombre_padre', 'label' => 'Nombre completo del padre', 'type' => 'text', 'required' => false],
|
||||
['name' => 'fecha_nacimiento_padre', 'label' => 'Fecha de nacimiento del padre', 'type' => 'date', 'required' => false],
|
||||
['name' => 'nombre_madre', 'label' => 'Nombre completo de la madre', 'type' => 'text', 'required' => false],
|
||||
['name' => 'fecha_nacimiento_madre', 'label' => 'Fecha de nacimiento de la madre', 'type' => 'date', 'required' => false],
|
||||
['name' => 'familiares_eeuu', 'label' => '¿Tiene familiares en EE.UU.?', 'type' => 'select', 'options' => ['Sí', 'No'], 'required' => false],
|
||||
['name' => 'relacion_familiar', 'label' => 'Relación con el familiar', 'type' => 'select', 'options' => ['Padres', 'Hijos', 'Hermanos', 'Pareja'], 'required' => false],
|
||||
['name' => 'status_migratorio_familiar', 'label' => 'Status migratorio del familiar', 'type' => 'select', 'options' => ['Residente legal', 'Ciudadano'], 'required' => false],
|
||||
|
||||
// Empleo (últimos 5 años)
|
||||
['type' => 'heading', 'label' => 'Empleo (últimos 5 años)'],
|
||||
['name' => 'nombre_empresa', 'label' => 'Nombre de la empresa', 'type' => 'text', 'required' => false],
|
||||
['name' => 'direccion_empresa', 'label' => 'Dirección de la empresa', 'type' => 'text', 'required' => false],
|
||||
['name' => 'telefono_empresa', 'label' => 'Teléfono de la empresa', 'type' => 'text', 'required' => false],
|
||||
['name' => 'puesto', 'label' => 'Puesto', 'type' => 'text', 'required' => false],
|
||||
['name' => 'fechas_trabajo', 'label' => 'Fechas de trabajo (inicio - fin)', 'type' => 'text', 'required' => false],
|
||||
|
||||
// Estudios
|
||||
['type' => 'heading', 'label' => 'Estudios'],
|
||||
['name' => 'nivel_estudios', 'label' => 'Nivel de estudios', 'type' => 'text', 'required' => false],
|
||||
['name' => 'nombre_escuela', 'label' => 'Nombre de la escuela', 'type' => 'text', 'required' => false],
|
||||
['name' => 'direccion_escuela', 'label' => 'Dirección de la escuela', 'type' => 'text', 'required' => false],
|
||||
['name' => 'telefono_escuela', 'label' => 'Teléfono de la escuela', 'type' => 'text', 'required' => false],
|
||||
['name' => 'curso_estudios', 'label' => 'Curso o carrera', 'type' => 'text', 'required' => false],
|
||||
['name' => 'fechas_estudios', 'label' => 'Fechas de estudio (inicio - fin)', 'type' => 'text', 'required' => false],
|
||||
|
||||
// Final
|
||||
['name' => 'comentarios', 'label' => 'Comentarios adicionales', 'type' => 'textarea', 'required' => false],
|
||||
],
|
||||
],
|
||||
|
||||
23
servicio.php
23
servicio.php
@@ -80,26 +80,39 @@ require_once __DIR__ . '/includes/header.php';
|
||||
</div>
|
||||
|
||||
<?php foreach ($servicio['campos_formulario'] as $campo): ?>
|
||||
<?php if ($campo['type'] === 'heading'): ?>
|
||||
<h3 class="form-heading"><?= htmlspecialchars($campo['label']) ?></h3>
|
||||
<?php else: ?>
|
||||
<div class="form-group">
|
||||
<label for="<?= htmlspecialchars($campo['name']) ?>">
|
||||
<?= htmlspecialchars($campo['label']) ?>
|
||||
<?= $campo['required'] ? ' *' : '' ?>
|
||||
<?= !empty($campo['required']) ? ' *' : '' ?>
|
||||
</label>
|
||||
<?php if ($campo['type'] === 'select'): ?>
|
||||
<select id="<?= htmlspecialchars($campo['name']) ?>" name="<?= htmlspecialchars($campo['name']) ?>" class="form-control" <?= $campo['required'] ? 'required' : '' ?>>
|
||||
<select id="<?= htmlspecialchars($campo['name']) ?>" name="<?= htmlspecialchars($campo['name']) ?>" class="form-control" <?= !empty($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'] === 'radio'): ?>
|
||||
<div class="form-radio-group">
|
||||
<?php foreach ($campo['options'] as $opt): ?>
|
||||
<label class="form-radio-label">
|
||||
<input type="radio" name="<?= htmlspecialchars($campo['name']) ?>" value="<?= htmlspecialchars($opt) ?>" <?= !empty($campo['required']) ? 'required' : '' ?>>
|
||||
<?= htmlspecialchars($opt) ?>
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?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>
|
||||
<textarea id="<?= htmlspecialchars($campo['name']) ?>" name="<?= htmlspecialchars($campo['name']) ?>" class="form-control" rows="4" <?= !empty($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' : '' ?>>
|
||||
<input type="date" id="<?= htmlspecialchars($campo['name']) ?>" name="<?= htmlspecialchars($campo['name']) ?>" class="form-control" <?= !empty($campo['required']) ? 'required' : '' ?>>
|
||||
<?php else: ?>
|
||||
<input type="text" id="<?= htmlspecialchars($campo['name']) ?>" name="<?= htmlspecialchars($campo['name']) ?>" class="form-control" <?= $campo['required'] ? 'required' : '' ?>>
|
||||
<input type="text" id="<?= htmlspecialchars($campo['name']) ?>" name="<?= htmlspecialchars($campo['name']) ?>" class="form-control" <?= !empty($campo['required']) ? 'required' : '' ?>>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<button type="submit" class="btn btn--primary btn--block">
|
||||
|
||||
Reference in New Issue
Block a user