MIPESCA_test / static /js /components /capture-form.js
Edoruin's picture
feat: hide GPS UI and move geocoding to GAS (Google Maps API)
8fc8282
/**
* Capture Form Component
* Data entry form for capture details
*/
const CaptureFormComponent = {
captureData: null,
location: null,
placeName: null,
render() {
const selectedSpecies = app.state.selectedSpecies || [];
return `
<div class="nav">
<button class="nav-back" onclick="app.navigate('species-selector')">←</button>
<h1>Detalles de Captura</h1>
</div>
<div class="content">
<div class="content">
<!-- Ubicación procesada en segundo plano -->
<form id="capture-form" onsubmit="CaptureFormComponent.submit(event)">
<!-- Datos Simplificados -->
<div class="card">
<h3>👤 Datos de Contacto</h3>
<div class="form-group">
<label for="port">Puerto / Desembarcadero</label>
<input type="text" id="port" name="port" placeholder="Ej: Las Terrenas, Bayahibe..." required>
</div>
<div class="form-group">
<label for="phone">Teléfono de Contacto</label>
<input type="tel" id="phone" name="phone" placeholder="809-000-0000">
</div>
<p style="font-size: 0.85rem; color: #666; margin-top: 10px;">
🔒 Tus datos personales serán anonimizados.
<a href="#" onclick="event.preventDefault(); app.navigate('info')" style="color: var(--primary-color); font-weight: 600;">Más información</a>
</p>
</div>
<!-- Detalles de Captura por Especie -->
<h3>🐟 Captura Específica</h3>
${selectedSpecies.map((speciesId, index) => {
const speciesInfo = SpeciesSelectorComponent.allSpecies.find(s => s.id === speciesId) || {};
return `
<div class="card">
${speciesId === 'otro' ? `
<div class="form-group">
<label for="custom-name-${index}">Nombre de la Especie</label>
<input
type="text"
id="custom-name-${index}"
placeholder="Ej: Pez León, Pulpo, etc."
required
>
</div>
` : `
<h3>${speciesInfo.commonName || speciesId}</h3>
`}
<div class="form-group">
<label for="quantity-${index}">Cantidad</label>
<input
type="number"
id="quantity-${index}"
name="quantity-${index}"
min="0.1"
step="0.1"
required
>
</div>
<div class="form-group">
<label for="unit-${index}">Unidad</label>
<select id="unit-${index}" name="unit-${index}" required>
<option value="lbs">Libras (lbs)</option>
<option value="units">Unidades</option>
</select>
</div>
</div>
`}).join('')}
<div class="card">
<h3>📉 Otros Detalles</h3>
<div class="form-group">
<label for="fishing-method">Método de Pesca (General)</label>
<select id="fishing-method" name="fishing-method" required>
<option value="">Seleccionar...</option>
<option value="Línea de mano">Línea de mano</option>
<option value="Nasa">Nasa</option>
<option value="Red de enmalle">Red de enmalle</option>
<option value="Palangre">Palangre</option>
<option value="Buceo">Buceo</option>
<option value="Otro">Otro</option>
</select>
</div>
<div class="form-group">
<label for="depth">Profundidad (Brazadas)</label>
<input
type="number"
id="depth"
name="depth"
min="0"
step="1"
required
>
</div>
</div>
<button type="submit" class="btn-primary btn-full">
Guardar Registro de Pesca
</button>
</form>
</div>
`;
},
async init() {
console.log('Capturando ubicación en segundo plano...');
try {
this.location = await geolocationService.getCurrentPosition();
console.log('Ubicación obtenida con éxito (silenciosa)');
} catch (error) {
console.warn('Error capturando ubicación inicial:', error);
}
},
getSpeciesName(speciesId) {
const species = SpeciesSelectorComponent.allSpecies.find(s => s.id === speciesId);
return species ? species.commonName : speciesId;
},
async submit(event) {
event.preventDefault();
// Refresco silencioso de GPS al enviar
try {
this.location = await geolocationService.getCurrentPosition();
} catch (e) {
console.warn('Refresh GPS falló, usando último valor conocido:', e);
}
if (!this.location) {
alert('Asegúrate de permitir el acceso al GPS para continuar. Es necesario para el registro científico.');
return;
}
const selectedSpecies = app.state.selectedSpecies || [];
const items = [];
// Collect data for each species
selectedSpecies.forEach((speciesId, index) => {
const speciesInfo = SpeciesSelectorComponent.allSpecies.find(s => s.id === speciesId) || {};
const quantity = parseFloat(document.getElementById(`quantity-${index}`).value);
const unit = document.getElementById(`unit-${index}`).value;
const customNameInput = document.getElementById(`custom-name-${index}`);
const customName = customNameInput ? customNameInput.value : null;
items.push({
speciesId: speciesId,
commonName: speciesId === 'otro' ? customName : speciesInfo.commonName,
category: speciesInfo.category || 'Otros',
quantity: quantity,
unit: unit,
customName: customName
});
});
// Create capture object
const capture = {
id: this.generateUUID(),
timestamp: new Date().toISOString(),
latitude: this.location.latitude,
longitude: this.location.longitude,
placeName: this.placeName,
species: selectedSpecies,
items: items,
fishingMethod: document.getElementById('fishing-method').value,
depth: parseFloat(document.getElementById('depth').value),
// Simplified fields
port: document.getElementById('port').value,
phone: document.getElementById('phone').value,
totalWeight: items.reduce((sum, item) => sum + (item.unit === 'lbs' ? item.quantity : 0), 0),
captureSource: 'device-gps',
synced: 0
};
// Save to IndexedDB
try {
await dbService.addCapture(capture);
// Store in app state for confirmation
app.state.lastCapture = capture;
// Navigate to confirmation
app.navigate('confirmation');
// Trigger sync if online
if (navigator.onLine) {
syncService.syncNow();
}
} catch (error) {
console.error('Error saving capture:', error);
alert('Error al guardar la captura. Por favor, intenta de nuevo.');
}
},
generateUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
};