Files
AidsMonitoring/frontend/js/org.js
T

241 lines
11 KiB
JavaScript

'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 = '<option value="">— Select port —</option>' +
_orgPorts.map(p => `<option value="${p.id}">${p.name}</option>`).join('');
} catch (e) {
document.getElementById('org-ports-body').innerHTML =
`<tr><td colspan="6" style="color:var(--red)">Error: ${e.message}</td></tr>`;
}
}
function _renderPorts() {
const tbody = document.getElementById('org-ports-body');
tbody.innerHTML = _orgPorts.map(p => `
<tr>
<td>${p.name}</td>
<td class="mono" style="font-size:0.7rem">${p.center_lat?.toFixed(4) ?? '--'}, ${p.center_lon?.toFixed(4) ?? '--'}</td>
<td>${p.default_zoom}</td>
<td style="font-size:0.7rem;color:var(--text-muted)">${p.chart_name || '--'}</td>
<td><span style="color:${p.activo ? 'var(--green)' : 'var(--red)'}">${p.activo ? 'ACTIVE' : 'OFF'}</span></td>
<td>
<button class="chart-row-btn" onclick="_editPort('${p.id}')">EDIT</button>
</td>
</tr>`).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 = '<option value="">— All companies —</option>' +
_orgCompanies.map(c => `<option value="${c.id}">${c.name}</option>`).join('');
sel.value = val;
});
} catch (e) {
document.getElementById('org-companies-body').innerHTML =
`<tr><td colspan="6" style="color:var(--red)">Error: ${e.message}</td></tr>`;
}
}
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 => `
<tr>
<td>${c.name}</td>
<td>${portMap[c.port_id] || '--'}</td>
<td class="mono" style="font-size:0.7rem">${c.contact_email || '--'}</td>
<td style="font-size:0.7rem">${c.contact_phone || '--'}</td>
<td><span style="color:${c.activa ? 'var(--green)' : 'var(--red)'}">${c.activa ? 'ACTIVE' : 'OFF'}</span></td>
<td><button class="chart-row-btn" onclick="_editCompany('${c.id}')">EDIT</button></td>
</tr>`).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 =
'<tr><td colspan="5" style="color:var(--text-muted)">Select a company first.</td></tr>';
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 => `
<tr>
<td>${cName}</td>
<td>${row.aid_nombre || '--'}</td>
<td class="mono">${row.mmsi || '--'}</td>
<td style="font-size:0.7rem;color:var(--text-muted)">${row.notas || '--'}</td>
<td>
<button class="chart-row-btn danger" onclick="_removeOwnership('${companyId}','${row.id}')">REMOVE</button>
</td>
</tr>`).join('')
: '<tr><td colspan="5" style="color:var(--text-muted)">No buoys assigned to this company.</td></tr>';
} catch (e) {
document.getElementById('org-ownership-body').innerHTML =
`<tr><td colspan="5" style="color:var(--red)">Error: ${e.message}</td></tr>`;
}
}
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'));