'use strict'; // Organization Management — Ports, Companies, BuoyOwnership let _orgPorts = []; let _orgCompanies = []; // ── Open modal ──────────────────────────────────────────────────────────────── window.openOrgModal = async function(tab = 'otab-ports') { _showModal('modal-org'); _activateOrgTab(tab); await _loadOrgPorts(); await _loadOrgCompanies(); }; function _activateOrgTab(id) { document.querySelectorAll('.otab-panel').forEach(p => p.classList.add('hidden')); document.querySelectorAll('.stab[data-otab]').forEach(b => b.classList.remove('active')); document.getElementById(id)?.classList.remove('hidden'); document.querySelector(`.stab[data-otab="${id}"]`)?.classList.add('active'); } document.querySelectorAll('.stab[data-otab]').forEach(btn => { btn.addEventListener('click', () => _activateOrgTab(btn.dataset.otab)); }); // ── Auth header helper ──────────────────────────────────────────────────────── function _ah() { return { 'Content-Type': 'application/json', Authorization: `Bearer ${window.Auth?.token()}` }; } // ── PORTS ───────────────────────────────────────────────────────────────────── async function _loadOrgPorts() { try { const r = await fetch(`${API}/org/ports`, { headers: _ah() }); _orgPorts = await r.json(); _renderPorts(); // populate company port selector const sel = document.getElementById('oc-port'); sel.innerHTML = '' + _orgPorts.map(p => ``).join(''); } catch (e) { document.getElementById('org-ports-body').innerHTML = `Error: ${e.message}`; } } function _renderPorts() { const tbody = document.getElementById('org-ports-body'); tbody.innerHTML = _orgPorts.map(p => ` ${p.name} ${p.center_lat?.toFixed(4) ?? '--'}, ${p.center_lon?.toFixed(4) ?? '--'} ${p.default_zoom} ${p.chart_name || '--'} ${p.activo ? 'ACTIVE' : 'OFF'} `).join(''); } document.getElementById('btn-port-add')?.addEventListener('click', async () => { const name = document.getElementById('op-name').value.trim(); const lat = parseFloat(document.getElementById('op-lat').value); const lon = parseFloat(document.getElementById('op-lon').value); const zoom = parseFloat(document.getElementById('op-zoom').value) || 12; const chart = document.getElementById('op-chart').value.trim(); const st = document.getElementById('org-ports-status'); if (!name) { st.textContent = 'Port name is required.'; return; } try { const r = await fetch(`${API}/org/ports`, { method: 'POST', headers: _ah(), body: JSON.stringify({ name, center_lat: isNaN(lat)?null:lat, center_lon: isNaN(lon)?null:lon, default_zoom: zoom, chart_name: chart || null }) }); if (!r.ok) throw new Error((await r.json()).detail); st.textContent = `Port "${name}" added.`; document.getElementById('op-name').value = ''; await _loadOrgPorts(); } catch (e) { st.textContent = `Error: ${e.message}`; } }); window._editPort = async function(portId) { const p = _orgPorts.find(x => x.id === portId); if (!p) return; const name = prompt('Port name:', p.name); if (!name) return; const chart = prompt('Chart folder (leave blank to keep):', p.chart_name || ''); try { await fetch(`${API}/org/ports/${portId}`, { method: 'PUT', headers: _ah(), body: JSON.stringify({ name, chart_name: chart || null }) }); await _loadOrgPorts(); } catch (e) { alert('Error: ' + e.message); } }; // ── COMPANIES ───────────────────────────────────────────────────────────────── async function _loadOrgCompanies() { try { const r = await fetch(`${API}/org/companies`, { headers: _ah() }); _orgCompanies = await r.json(); _renderCompanies(); // populate ownership selectors const sels = [document.getElementById('ow-filter-company'), document.getElementById('ow-company-sel')]; sels.forEach(sel => { if (!sel) return; const val = sel.value; sel.innerHTML = '' + _orgCompanies.map(c => ``).join(''); sel.value = val; }); } catch (e) { document.getElementById('org-companies-body').innerHTML = `Error: ${e.message}`; } } function _renderCompanies() { const portMap = Object.fromEntries(_orgPorts.map(p => [p.id, p.name])); const tbody = document.getElementById('org-companies-body'); tbody.innerHTML = _orgCompanies.map(c => ` ${c.name} ${portMap[c.port_id] || '--'} ${c.contact_email || '--'} ${c.contact_phone || '--'} ${c.activa ? 'ACTIVE' : 'OFF'} `).join(''); } document.getElementById('btn-company-add')?.addEventListener('click', async () => { const name = document.getElementById('oc-name').value.trim(); const portId = document.getElementById('oc-port').value; const email = document.getElementById('oc-email').value.trim(); const phone = document.getElementById('oc-phone').value.trim(); const st = document.getElementById('org-companies-status'); if (!name) { st.textContent = 'Company name is required.'; return; } try { const r = await fetch(`${API}/org/companies`, { method: 'POST', headers: _ah(), body: JSON.stringify({ name, port_id: portId || null, contact_email: email || null, contact_phone: phone || null }) }); if (!r.ok) throw new Error((await r.json()).detail); st.textContent = `Company "${name}" added.`; document.getElementById('oc-name').value = ''; await _loadOrgCompanies(); } catch (e) { st.textContent = `Error: ${e.message}`; } }); window._editCompany = async function(companyId) { const c = _orgCompanies.find(x => x.id === companyId); if (!c) return; const name = prompt('Company name:', c.name); if (!name) return; const portId = prompt('Port ID (leave blank to keep):', c.port_id || ''); try { await fetch(`${API}/org/companies/${companyId}`, { method: 'PUT', headers: _ah(), body: JSON.stringify({ name, port_id: portId || null }) }); await _loadOrgCompanies(); } catch (e) { alert('Error: ' + e.message); } }; // ── BUOY OWNERSHIP ──────────────────────────────────────────────────────────── document.getElementById('btn-ow-load')?.addEventListener('click', _loadOwnership); async function _loadOwnership() { const companyId = document.getElementById('ow-filter-company').value; if (!companyId) { document.getElementById('org-ownership-body').innerHTML = 'Select a company first.'; return; } try { const r = await fetch(`${API}/org/companies/${companyId}/buoys`, { headers: _ah() }); const rows = await r.json(); const cName = _orgCompanies.find(c => c.id === companyId)?.name || companyId; document.getElementById('org-ownership-body').innerHTML = rows.length ? rows.map(row => ` ${cName} ${row.aid_nombre || '--'} ${row.mmsi || '--'} ${row.notas || '--'} `).join('') : 'No buoys assigned to this company.'; } catch (e) { document.getElementById('org-ownership-body').innerHTML = `Error: ${e.message}`; } } window._removeOwnership = async function(companyId, ownershipId) { if (!confirm('Remove this buoy assignment?')) return; try { const r = await fetch(`${API}/org/companies/${companyId}/buoys/${ownershipId}`, { method: 'DELETE', headers: _ah() }); if (!r.ok) throw new Error((await r.json()).detail); // Refresh cache on server await fetch(`${API}/org/refresh`, { method: 'POST', headers: _ah() }); await _loadOwnership(); } catch (e) { alert('Error: ' + e.message); } }; document.getElementById('btn-ow-assign')?.addEventListener('click', async () => { const companyId = document.getElementById('ow-company-sel').value; const aidId = document.getElementById('ow-aid-id').value.trim(); const mmsi = document.getElementById('ow-mmsi').value.trim(); const notas = document.getElementById('ow-notes').value.trim(); const st = document.getElementById('org-ownership-status'); if (!companyId) { st.textContent = 'Select a company.'; return; } if (!aidId && !mmsi) { st.textContent = 'Provide an Aid ID or MMSI.'; return; } try { const r = await fetch(`${API}/org/companies/${companyId}/buoys`, { method: 'POST', headers: _ah(), body: JSON.stringify({ aid_id: aidId || null, mmsi: mmsi || null, notas: notas || null }) }); if (!r.ok) throw new Error((await r.json()).detail); // Refresh cache on server await fetch(`${API}/org/refresh`, { method: 'POST', headers: _ah() }); st.textContent = 'Buoy assigned.'; document.getElementById('ow-aid-id').value = ''; document.getElementById('ow-mmsi').value = ''; // Auto-load the company we just assigned document.getElementById('ow-filter-company').value = companyId; await _loadOwnership(); } catch (e) { st.textContent = `Error: ${e.message}`; } }); // ── Close buttons ───────────────────────────────────────────────────────────── document.getElementById('btn-close-org')?.addEventListener('click', () => _hideModal('modal-org')); document.getElementById('btn-close-org2')?.addEventListener('click', () => _hideModal('modal-org'));