Files
AidsMonitoring/frontend/index.html
T

894 lines
47 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AidsMonitoring — Maritime Traffic System</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@v9.2.4/ol.css">
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<!-- ── PANTALLA DE LOGIN INICIAL ──────────────────────────────────────── -->
<div id="login-screen">
<div class="ls-box">
<div class="ls-logo">AIDS<span>MONITORING</span></div>
<div class="ls-subtitle">MARITIME TRAFFIC SYSTEM</div>
<div class="ls-version">v1.0</div>
<div class="ls-fields">
<div class="form-field">
<label class="form-label">Username</label>
<input class="form-input" id="ls-user" type="text" placeholder="username" autocomplete="username">
</div>
<div class="form-field" style="margin-top:10px">
<label class="form-label">Password</label>
<input class="form-input" id="ls-pass" type="password" placeholder="••••••••" autocomplete="current-password">
</div>
<div id="ls-error" class="modal-error hidden" style="margin-top:10px"></div>
<button class="btn-modal-primary" id="ls-submit" style="width:100%;margin-top:16px;padding:10px">LOGIN</button>
</div>
<div class="ls-footer">AidsMonitoring &copy; 2026</div>
</div>
</div>
<!-- ── APP PRINCIPAL (oculta hasta login) ────────────────────────────── -->
<div id="app" class="hidden">
<header>
<div class="header-brand">
<svg class="app-icon" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="18" cy="18" r="15.5" stroke="#06b6d4" stroke-width="1.5" opacity="0.45"/>
<circle cx="18" cy="18" r="10" stroke="#06b6d4" stroke-width="1" opacity="0.35"/>
<circle cx="18" cy="18" r="3" fill="#06b6d4"/>
<line x1="18" y1="2.5" x2="18" y2="9" stroke="#06b6d4" stroke-width="2" stroke-linecap="round"/>
<path d="M18 18 L18 8 L29 7 Z" fill="#06b6d4" opacity="0.22"/>
<line x1="18" y1="18" x2="29" y2="7" stroke="#06b6d4" stroke-width="1.5" stroke-linecap="round"/>
<line x1="2" y1="18" x2="34" y2="18" stroke="#06b6d4" stroke-width="0.5" opacity="0.2"/>
<line x1="18" y1="2" x2="18" y2="34" stroke="#06b6d4" stroke-width="0.5" opacity="0.2"/>
</svg>
<div>
<div class="logo">AIDS<span>MONITORING</span></div>
<div class="company-tagline" id="company-tagline">MARITIME TRAFFIC SYSTEM</div>
</div>
</div>
<!-- MENÚ PRINCIPAL -->
<nav id="main-nav">
<div class="nav-item" id="nav-settings">
<span data-i18n="nav.settings">SETTINGS</span>
<div class="nav-dropdown" id="dd-settings">
<div class="dd-item" data-action="settings-datasource" data-i18n="dd.datasource">Data Source / AIS</div>
<div class="dd-item" data-action="settings-station" data-i18n="dd.station">Station &amp; Antenna</div>
<div class="dd-item" data-action="settings-alerts" data-i18n="dd.alerts">Alert Parameters</div>
<div class="dd-item" data-action="settings-equipment">Connected Equipment</div>
<div class="dd-item dd-sep" data-action="lamps-catalog">Lamp Catalog</div>
<div class="dd-item" data-action="contacts-catalog">Contacts (port auth / owners)</div>
</div>
</div>
<div class="nav-item" id="nav-charts">
<span data-i18n="nav.charts">CHARTS</span>
<div class="nav-dropdown" id="dd-charts">
<div class="dd-item" data-action="charts-catalog" data-i18n="dd.installed">Installed Charts</div>
<div class="dd-item" data-action="charts-install" data-i18n="dd.install">Install Chart Cell (.000)</div>
<div class="dd-item dd-sep" data-action="charts-noaa" data-i18n="dd.noaa">Download NOAA Free Charts</div>
</div>
</div>
<div class="nav-item" id="nav-reports">
<span data-i18n="nav.reports">REPORTS</span>
<div class="nav-dropdown" id="dd-reports">
<div class="dd-item" data-action="recordings-list" data-i18n="dd.recordings">Vessel Recordings (VDR)</div>
<div class="dd-item" data-action="ais-history" data-i18n="dd.history">AIS Track History</div>
<div class="dd-item dd-sep" data-action="export-data" data-i18n="dd.export">Export Data (CSV)</div>
</div>
</div>
<div class="nav-item" id="nav-users">
<span data-i18n="nav.users">USERS</span>
<div class="nav-dropdown" id="dd-users">
<div class="dd-item" data-action="users-list" data-i18n="dd.manage">Manage Users</div>
<div class="dd-item" data-action="users-create" data-i18n="dd.create">Create User</div>
<div class="dd-item dd-sep" data-action="org-management">Organizations &amp; Ports</div>
</div>
</div>
</nav>
<div class="header-right">
<div class="stat-block">
<span class="stat-label">UTC</span>
<span id="clock" class="stat-value mono">--:--:--</span>
</div>
<div class="stat-block">
<span class="stat-label" data-i18n="stat.vessels">VESSELS</span>
<span id="vessel-count" class="stat-value mono">0</span>
</div>
<div class="stat-block">
<span class="stat-label" data-i18n="stat.aids">AIDS</span>
<span id="aid-count" class="stat-value mono">0</span>
</div>
<div class="stat-block">
<span class="stat-label" data-i18n="stat.link">LINK</span>
<span id="ws-status" class="link-indicator offline">OFFLINE</span>
</div>
<div id="session-badge" class="session-badge"></div>
</div>
</header>
<div class="main-layout">
<!-- SECTOR 1: CARTOGRAFIA -->
<div id="map-sector">
<div id="map-toolbar">
<span class="toolbar-label" data-i18n="tb.port">PORT</span>
<div class="port-search-wrap">
<input id="port-search" class="port-search-input" type="text"
data-i18n-placeholder="tb.port.ph" placeholder="Search worldwide port..." autocomplete="off">
<div id="port-suggestions" class="port-suggestions hidden"></div>
</div>
<div class="toolbar-sep"></div>
<span class="toolbar-label" data-i18n="tb.display">DISPLAY</span>
<button class="tb-btn active" data-filter="all" data-i18n="tb.all">ALL</button>
<button class="tb-btn" data-filter="vessels" data-i18n="tb.vessels">VESSELS</button>
<button class="tb-btn" data-filter="aids" data-i18n="tb.aids">AIDS</button>
<button class="tb-btn" data-filter="alerts" data-i18n="tb.alerts">ALERTS</button>
<div class="toolbar-sep"></div>
<span class="toolbar-label" data-i18n="tb.layer">LAYER</span>
<button class="tb-btn active" id="toggle-world" data-i18n="tb.world" title="OSM world raster basemap">WORLD</button>
<button class="tb-btn active" id="toggle-seamap" data-i18n="tb.seamark" title="OpenSeaMap overlay">SEAMARK</button>
<button class="tb-btn active" id="toggle-enc" data-i18n="tb.aids" title="S-57 aids to navigation (buoys, beacons, lights)">AIDS</button>
<button class="tb-btn active" id="toggle-land" data-i18n="tb.land" title="S-57 terrain: land areas, coastline, structures">LAND</button>
<button class="tb-btn active" id="toggle-depths" data-i18n="tb.bathy" title="S-57 bathymetry: depth areas, contours, soundings">BATHY</button>
<button class="tb-btn active" id="toggle-hazards" data-i18n="tb.hazards" title="S-57 hazards: wrecks, obstructions, rocks">HAZARDS</button>
<button class="tb-btn active" id="toggle-zones" data-i18n="tb.zones" title="S-57 zones: restricted, anchorage, traffic lanes, fairways">ZONES</button>
<div class="toolbar-sep"></div>
<button class="tb-btn" id="toggle-night" data-i18n="tb.night">NIGHT</button>
<div class="toolbar-sep"></div>
<button class="tb-btn active" id="toggle-lang">EN/ES</button>
<div class="toolbar-sep"></div>
<button class="tb-btn" id="btn-sdr" title="Launch AIS-catcher (RTL-SDR receiver)">SDR</button>
</div>
<div id="map"></div>
<div id="map-coords" class="mono">LAT -- LON --</div>
</div>
<!-- SECTOR 2: COLUMNA DERECHA -->
<div id="right-column">
<div id="info-sector">
<div class="sector-header" data-i18n="sector.info">OBJECT INFO</div>
<div id="info-content">
<div class="no-selection">
<div class="no-sel-line"></div>
<span data-i18n="no.sel">SELECT OBJECT ON CHART</span>
<div class="no-sel-line"></div>
</div>
</div>
</div>
<div id="panel-divider"></div>
<div id="events-sector">
<div class="sector-header">
<span data-i18n="sector.events">EVENTS &amp; ALERTS</span>
<span id="alert-badge" class="alert-badge hidden">0</span>
</div>
<div id="events-list"></div>
</div>
</div>
</div>
<!-- ── BARRA DE ESTADO INFERIOR ──────────────────────────────────────── -->
<div id="status-bar">
<div class="sb-group"><span class="sb-dot grey" id="sb-dot-ais"></span><span class="sb-label" id="sb-ais">AIS: SIMULATOR</span></div>
<div class="sb-group"><span class="sb-dot grey" id="sb-dot-gps"></span><span class="sb-label" id="sb-gps">GPS: --</span></div>
<div class="sb-group"><span class="sb-dot grey" id="sb-dot-nmea"></span><span class="sb-label" id="sb-nmea">NMEA: --</span></div>
<div class="sb-group"><span class="sb-dot grey" id="sb-dot-ws"></span><span class="sb-label" id="sb-ws">WS: OFFLINE</span></div>
<div class="sb-sep"></div>
<div class="sb-user" id="sb-user"></div>
</div>
</div><!-- /app -->
<div id="tooltip" class="tooltip hidden"></div>
<!-- Panel flotante de cartas disponibles en área actual -->
<div id="chart-nearby-panel" class="chart-nearby-panel hidden">
<div class="cnp-header">
<span class="cnp-title">CHARTS IN VIEW</span>
<button class="cnp-close" onclick="window._cnpClose && _cnpClose()">&times;</button>
</div>
<div id="cnp-body"></div>
</div>
<!-- ── MODAL OVERLAY ──────────────────────────────────────────────────── -->
<div id="modal-overlay" class="modal-overlay hidden">
<!-- LOGIN (edición) -->
<div id="modal-login" class="modal hidden">
<div class="modal-header">
<span class="modal-title">AUTHENTICATION REQUIRED</span>
<button class="modal-close" id="btn-close-login">&times;</button>
</div>
<div class="modal-body">
<div class="modal-subtitle">Admin or Superadmin credentials required.</div>
<div class="form-field" style="margin-top:16px">
<label class="form-label">Username</label>
<input class="form-input" id="login-user" type="text" placeholder="username">
</div>
<div class="form-field" style="margin-top:10px">
<label class="form-label">Password</label>
<input class="form-input" id="login-pass" type="password" placeholder="••••••••">
</div>
<div id="login-error" class="modal-error hidden"></div>
</div>
<div class="modal-footer">
<button class="btn-modal-primary" id="btn-login-submit">LOGIN</button>
<button class="btn-modal-secondary" id="btn-login-cancel">CANCEL</button>
</div>
</div>
<!-- EDICIÓN AYUDA -->
<div id="modal-edit" class="modal hidden">
<div class="modal-header">
<div>
<span class="modal-title">EDIT AID DATA</span>
<span id="edit-aid-name" class="modal-subtitle-inline"></span>
</div>
<button class="modal-close" id="btn-close-edit">&times;</button>
</div>
<div class="modal-body" id="modal-edit-body"></div>
<div class="modal-footer">
<button class="btn-modal-primary" id="btn-edit-submit">SAVE CHANGES</button>
<button class="btn-modal-secondary" id="btn-edit-cancel">CANCEL</button>
<span id="edit-save-status" class="save-status"></span>
</div>
</div>
<!-- GESTIÓN DE USUARIOS -->
<div id="modal-users" class="modal modal-wide hidden">
<div class="modal-header">
<span class="modal-title">USER MANAGEMENT</span>
<button class="modal-close" id="btn-close-users">&times;</button>
</div>
<div class="modal-body" id="modal-users-body"></div>
<div class="modal-footer">
<button class="btn-modal-primary" id="btn-user-new">NEW USER</button>
<button class="btn-modal-secondary" id="btn-close-users2">CLOSE</button>
</div>
</div>
<!-- CARTAS NÁUTICAS -->
<div id="modal-charts" class="modal hidden" style="max-width:680px">
<div class="modal-header">
<span class="modal-title">NAUTICAL CHARTS — S-57 ENC</span>
<button class="modal-close" id="btn-close-charts">&times;</button>
</div>
<div class="modal-body" id="modal-charts-body">
<!-- TABS -->
<div class="stab-bar" style="margin-bottom:14px">
<button class="stab active" data-ctab="tab-catalog">NOAA CATALOG</button>
<button class="stab" data-ctab="tab-installed">INSTALLED</button>
<button class="stab" data-ctab="tab-upload">UPLOAD FILE</button>
<button class="stab" data-ctab="tab-buy">BUY CHARTS</button>
</div>
<!-- TAB: NOAA CATALOG -->
<div id="tab-catalog" class="ctab-panel">
<div style="font-size:0.7rem;color:var(--text-muted);margin-bottom:10px">
Click DOWNLOAD to fetch directly from NOAA servers and install. No manual download needed.
</div>
<table class="chart-table" id="noaa-catalog-table">
<thead><tr><th>Cell</th><th>Description</th><th>Status</th><th></th></tr></thead>
<tbody id="noaa-catalog-body"></tbody>
</table>
</div>
<!-- TAB: INSTALLED -->
<div id="tab-installed" class="ctab-panel hidden">
<div style="display:flex;justify-content:flex-end;margin-bottom:8px">
<button class="chart-row-btn" id="btn-rebuild-all"
onclick="rebuildAllCells()"
title="Re-parse all installed charts and reload map layers">
↺ REBUILD ALL
</button>
</div>
<table class="chart-table" id="installed-table">
<thead><tr><th>Cell</th><th>Features</th><th>IALA</th><th style="min-width:140px"></th></tr></thead>
<tbody id="installed-body"></tbody>
</table>
<div id="installed-empty" style="display:none;color:var(--text-muted);font-size:0.75rem;padding:16px 0">
No charts installed yet.
</div>
</div>
<!-- TAB: UPLOAD -->
<div id="tab-upload" class="ctab-panel hidden">
<div class="form-field">
<label class="form-label">Chart cell (.000) or ZIP archive *</label>
<input class="form-input" id="chart-file" type="file" accept=".000,.zip" style="padding:4px">
</div>
<div id="chart-upload-status" style="margin-top:10px;font-size:0.75rem"></div>
<button class="btn-modal-primary" id="btn-chart-upload" style="margin-top:12px">INSTALL</button>
</div>
<!-- TAB: BUY -->
<div id="tab-buy" class="ctab-panel hidden">
<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px">
<div class="chart-source-card" onclick="window.open('https://www.admiralty.co.uk/digital-services/digital-charts/admiralty-vector-chart-service','_blank')">
<div class="chart-card-title">UKHO / AVCS</div>
<div class="chart-card-sub">Licensed · Worldwide</div>
<div class="chart-card-desc">UK Hydrographic Office. Global coverage, encrypted S-63. Requires permit file.</div>
<div class="chart-card-btn">BUY / INFO</div>
</div>
<div class="chart-source-card" onclick="window.open('https://www.primar.org','_blank')">
<div class="chart-card-title">PRIMAR</div>
<div class="chart-card-sub">Licensed · Worldwide</div>
<div class="chart-card-desc">Norwegian Hydrographic Service distribution. Buy by cell or subscription.</div>
<div class="chart-card-btn">BUY / INFO</div>
</div>
<div class="chart-source-card" onclick="window.open('https://www.dimar.mil.co','_blank')">
<div class="chart-card-title">DIMAR</div>
<div class="chart-card-sub">Colombia · Oficial</div>
<div class="chart-card-desc">Dirección General Marítima — cartas de Colombia. Contactar para licencias ENC.</div>
<div class="chart-card-btn">INFO / CONTACTO</div>
</div>
<div class="chart-source-card" onclick="window.open('https://www.ic-enc.org','_blank')">
<div class="chart-card-title">IC-ENC</div>
<div class="chart-card-sub">Licensed · International</div>
<div class="chart-card-desc">International Centre for ENC. Worldwide coverage, S-63 encrypted.</div>
<div class="chart-card-btn">BUY / INFO</div>
</div>
</div>
</div>
<div id="chart-install-status" style="margin-top:10px;font-size:0.75rem"></div>
</div>
<div class="modal-footer">
<button class="btn-modal-secondary" id="btn-rebuild-cache" onclick="rebuildAllCells()" title="Re-parse all installed charts and reload map">↺ REBUILD ALL SYMBOLS</button>
<button class="btn-modal-secondary" id="btn-close-charts2">CLOSE</button>
<span id="chart-save-status" class="save-status"></span>
</div>
</div>
<!-- CREAR / EDITAR USUARIO -->
<div id="modal-user-form" class="modal hidden">
<div class="modal-header">
<span class="modal-title" id="user-form-title">CREATE USER</span>
<button class="modal-close" id="btn-close-user-form">&times;</button>
</div>
<div class="modal-body">
<div class="form-field">
<label class="form-label">Username *</label>
<input class="form-input" id="uf-username" type="text" placeholder="login name">
</div>
<div class="form-field" style="margin-top:10px">
<label class="form-label">Full name *</label>
<input class="form-input" id="uf-nombre" type="text" placeholder="Full name">
</div>
<div class="form-field" style="margin-top:10px">
<label class="form-label">Email</label>
<input class="form-input" id="uf-email" type="email" placeholder="email@company.com">
</div>
<div class="form-field" style="margin-top:10px">
<label class="form-label">Password *</label>
<input class="form-input" id="uf-password" type="password" placeholder="••••••••">
</div>
<div class="form-field" style="margin-top:10px">
<label class="form-label">Role *</label>
<select class="form-input-select" id="uf-role">
<option value="USER">USER — Read only (client)</option>
<option value="CLIENT_ADMIN">CLIENT ADMIN — Can record (client)</option>
<option value="ADMIN">ADMIN — Can edit aids</option>
<option value="SUPERADMIN">SUPERADMIN — Full access</option>
</select>
</div>
<div class="form-field" style="margin-top:10px" id="uf-company-row">
<label class="form-label">Company (client port) *</label>
<select class="form-input-select" id="uf-company">
<option value="">— Select company —</option>
</select>
<div style="font-size:0.7rem;color:var(--text-muted);margin-top:4px" id="uf-company-hint"></div>
</div>
<div id="uf-error" class="modal-error hidden" style="margin-top:10px"></div>
</div>
<div class="modal-footer">
<button class="btn-modal-primary" id="btn-uf-save">CREATE USER</button>
<button class="btn-modal-secondary" id="btn-uf-cancel">CANCEL</button>
</div>
</div>
<!-- SETTINGS -->
<div id="modal-settings" class="modal modal-wide hidden">
<div class="modal-header">
<span class="modal-title">SYSTEM SETTINGS</span>
<button class="modal-close" id="btn-close-settings">&times;</button>
</div>
<div class="modal-body">
<div class="settings-tabs">
<button class="stab active" data-tab="ais">AIS SOURCE</button>
<button class="stab" data-tab="station">STATION</button>
<button class="stab" data-tab="alerts">ALERT THRESHOLDS</button>
<button class="stab" data-tab="equipment">CONNECTED EQUIPMENT</button>
<button class="stab" data-tab="smtp">EMAIL (SMTP)</button>
</div>
<!-- AIS Source -->
<div class="stab-panel" id="stab-ais">
<div class="form-field">
<label class="form-label">AIS Input Source</label>
<select class="form-input-select" id="set-ais-source">
<option value="SIMULATOR">Simulator (testing / demo)</option>
<option value="SDR">RTL-SDR — AIS-catcher (auto-launch)</option>
<option value="SERIAL">Serial Port — AIS transponder / NMEA mux</option>
<option value="NETWORK">Network TCP/UDP (aggregator / kplex)</option>
</select>
</div>
<div class="form-field" style="margin-top:12px" id="field-serial-port">
<label class="form-label">Serial Port (COM / tty)</label>
<input class="form-input" id="set-serial-port" placeholder="COM3 or /dev/ttyUSB0">
</div>
<div class="form-field" style="margin-top:10px" id="field-baud">
<label class="form-label">Baud Rate</label>
<select class="form-input-select" id="set-baud">
<option value="38400">38400 — AIS standard (NMEA 0183)</option>
<option value="115200">115200 — High-speed USB</option>
<option value="4800">4800 — Legacy NMEA</option>
<option value="9600">9600</option>
</select>
</div>
<div class="form-field" style="margin-top:10px hidden" id="field-net-addr">
<label class="form-label">Network Address : Port</label>
<input class="form-input" id="set-net-addr" placeholder="192.168.1.100:10110">
</div>
</div>
<!-- Station -->
<div class="stab-panel hidden" id="stab-station">
<div class="field-row-modal">
<div class="form-field">
<label class="form-label">Station Name</label>
<input class="form-input" id="set-station-name" placeholder="e.g. Barranquilla — Central Station">
</div>
<div class="form-field">
<label class="form-label">IALA Region (buoy colors)</label>
<select class="form-input-select" id="set-iala-region" title="IALA-A: red=port. IALA-B Americas: green=port (Red Right Returning)">
<option value="B">IALA-B — Américas / Japan / Korea (Green=Port)</option>
<option value="A">IALA-A — Europa / Africa / Asia (Red=Port)</option>
</select>
</div>
</div>
<div class="form-field" style="margin-top:10px">
<label class="form-label">GPS Serial Port (leave blank for auto-detect)</label>
<input class="form-input" id="set-gps-port" placeholder="COM8 or /dev/ttyUSB0 — blank = auto-scan">
</div>
<div class="field-row-modal" style="margin-top:10px">
<div class="form-field">
<label class="form-label">Antenna Latitude</label>
<input class="form-input" id="set-ant-lat" type="number" step="0.000001" placeholder="10.987800">
</div>
<div class="form-field">
<label class="form-label">Antenna Longitude</label>
<input class="form-input" id="set-ant-lon" type="number" step="0.000001" placeholder="-74.804000">
</div>
</div>
<div class="form-field" style="margin-top:10px">
<label class="form-label">Antenna Height (m ASL)</label>
<input class="form-input" id="set-ant-height" type="number" placeholder="25">
</div>
<div class="form-field" style="margin-top:10px">
<label class="form-label">Notes</label>
<textarea class="form-textarea" id="set-station-notes" style="height:56px" placeholder="Description or notes about this station"></textarea>
</div>
</div>
<!-- Connected Equipment -->
<div class="stab-panel hidden" id="stab-equipment">
<div style="display:flex;align-items:center;gap:12px;margin-bottom:14px">
<button class="btn-modal-primary" id="btn-scan-ports" style="padding:6px 18px">SCAN PORTS</button>
<span id="scan-status" style="font-size:0.72rem;color:var(--text-muted)">Click SCAN PORTS to detect connected equipment</span>
</div>
<div id="equipment-list"></div>
</div>
<!-- Alerts -->
<div class="stab-panel hidden" id="stab-alerts">
<div class="modal-section-label">AID DISPLACEMENT</div>
<div class="field-row-modal">
<div class="form-field">
<label class="form-label">Warning threshold (m)</label>
<input class="form-input" id="set-disp-warn" type="number" value="10">
</div>
<div class="form-field">
<label class="form-label">Alarm threshold (m)</label>
<input class="form-input" id="set-disp-alarm" type="number" value="15">
</div>
</div>
<div class="modal-section-label" style="margin-top:14px">VESSEL PROXIMITY</div>
<div class="field-row-modal">
<div class="form-field">
<label class="form-label">Warning distance (m)</label>
<input class="form-input" id="set-prox-warn" type="number" value="300">
</div>
<div class="form-field">
<label class="form-label">Auto-record trigger (m)</label>
<input class="form-input" id="set-rec-trigger" type="number" value="200">
</div>
</div>
<div class="modal-section-label" style="margin-top:14px">BATTERY (ATON)</div>
<div class="field-row-modal">
<div class="form-field">
<label class="form-label">Low battery warning (V)</label>
<input class="form-input" id="set-batt-warn" type="number" step="0.1" value="11.5">
</div>
<div class="form-field">
<label class="form-label">Critical battery alarm (V)</label>
<input class="form-input" id="set-batt-alarm" type="number" step="0.1" value="10.8">
</div>
</div>
</div>
<!-- SMTP / Email -->
<div class="stab-panel hidden" id="stab-smtp">
<div style="font-size:0.72rem;color:var(--text-muted);margin-bottom:10px">
Configure your organisation's email account so REPORT emails are sent from
the system (no popup, no operator email client).
For Gmail use <code>smtp.gmail.com</code> port <code>587</code> with an
<a href="https://myaccount.google.com/apppasswords" target="_blank" style="color:var(--accent)">app password</a>.
</div>
<div class="field-row-modal">
<div class="form-field">
<label class="form-label">SMTP Host</label>
<input class="form-input" id="set-smtp-host" placeholder="smtp.gmail.com">
</div>
<div class="form-field">
<label class="form-label">Port</label>
<input class="form-input" id="set-smtp-port" type="number" value="587">
</div>
</div>
<div class="field-row-modal" style="margin-top:10px">
<div class="form-field">
<label class="form-label">SMTP Username</label>
<input class="form-input" id="set-smtp-user" placeholder="user@yourdomain.com">
</div>
<div class="form-field">
<label class="form-label">SMTP Password (app password)</label>
<input class="form-input" id="set-smtp-password" type="password" placeholder="••••••••">
</div>
</div>
<div class="field-row-modal" style="margin-top:10px">
<div class="form-field">
<label class="form-label">From address (sender)</label>
<input class="form-input" id="set-smtp-from" placeholder="monitoreo@yourdomain.com">
</div>
<div class="form-field">
<label class="form-label">From name (display)</label>
<input class="form-input" id="set-smtp-from-name" placeholder="AidsMonitoring">
</div>
</div>
<div class="form-field" style="margin-top:10px">
<label class="form-label" style="display:flex;align-items:center;gap:6px">
<input type="checkbox" id="set-smtp-tls" checked> Use STARTTLS (port 587). Disable for SSL on port 465.
</label>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn-modal-primary" id="btn-settings-save">SAVE SETTINGS</button>
<button class="btn-modal-secondary" id="btn-close-settings2">CLOSE</button>
<span id="settings-status" class="save-status"></span>
</div>
</div>
<!-- RECORDINGS / VDR -->
<div id="modal-recordings" class="modal modal-wide hidden">
<div class="modal-header">
<span class="modal-title">VESSEL RECORDINGS — VDR</span>
<button class="modal-close" id="btn-close-recordings">&times;</button>
</div>
<div class="modal-body">
<div style="display:flex;gap:10px;margin-bottom:14px;align-items:flex-end">
<div class="form-field" style="flex:1">
<label class="form-label">MMSI or Vessel Name</label>
<input class="form-input" id="rec-filter-mmsi" placeholder="All vessels">
</div>
<div class="form-field">
<label class="form-label">Date From</label>
<input class="form-input" id="rec-filter-from" type="date">
</div>
<div class="form-field">
<label class="form-label">Date To</label>
<input class="form-input" id="rec-filter-to" type="date">
</div>
<button class="btn-modal-primary" id="btn-rec-search" style="padding:5px 14px;margin-bottom:0">SEARCH</button>
</div>
<div id="modal-recordings-body">
<div style="color:var(--text-muted);font-size:0.75rem;padding:20px 0;text-align:center">
Select filters above and press SEARCH to load recordings.
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn-modal-secondary" id="btn-close-recordings2">CLOSE</button>
</div>
</div>
<!-- REPORT ALERT -->
<div id="modal-report" class="modal modal-wide hidden">
<div class="modal-header">
<span class="modal-title">REPORT ALERT — Notify port authority &amp; aid owner</span>
<button class="modal-close" id="btn-close-report">&times;</button>
</div>
<div class="modal-body">
<div id="report-alert-summary" style="background:#1a2a3a;border-left:3px solid var(--yellow);padding:8px 12px;margin-bottom:12px;font-size:0.78rem"></div>
<div class="form-field" style="margin-bottom:10px">
<label class="form-label">Message (editable)</label>
<textarea id="report-message" class="form-textarea" style="height:90px;width:100%"></textarea>
</div>
<div id="report-recipients">
<div style="color:var(--text-muted);font-size:0.78rem">Loading recipients…</div>
</div>
<div id="report-status" class="save-status" style="margin-top:10px"></div>
</div>
<div class="modal-footer">
<button class="btn-modal-secondary" id="btn-close-report2">CLOSE</button>
</div>
</div>
<!-- CONTACTS CATALOG -->
<div id="modal-contacts" class="modal modal-wide hidden">
<div class="modal-header">
<span class="modal-title">CONTACTS — Port authorities &amp; aid owners</span>
<button class="modal-close" id="btn-close-contacts">&times;</button>
</div>
<div class="modal-body">
<div style="font-size:0.72rem;color:var(--text-muted);margin-bottom:10px">
Each row is a <strong>contact person</strong> (or office) that gets notified.<br>
The <strong>Organization</strong> column holds the port name (for PORT_AUTHORITY) or
the company name (for OWNER) — it must match exactly the
<code>puerto_responsable</code> / <code>empresa_responsable</code> field of the aid
so REPORT can route alerts to the right people.
</div>
<table class="chart-table" id="contacts-table">
<thead><tr>
<th>Role</th>
<th>Contact Person / Office</th>
<th>Organization (port or company)</th>
<th>Email</th><th>Phone</th><th>WhatsApp</th><th>Pref.</th><th></th>
</tr></thead>
<tbody id="contacts-body"></tbody>
<tfoot>
<tr id="contacts-newrow">
<td>
<select class="form-input-select" id="ct-new-role">
<option value="PORT_AUTHORITY">PORT AUTH</option>
<option value="OWNER">OWNER</option>
</select>
</td>
<td><input class="form-input" id="ct-new-name" placeholder="e.g. Capt. J. Pérez / Maritime Office"></td>
<td><input class="form-input" id="ct-new-match" placeholder="Port or company name"></td>
<td><input class="form-input" id="ct-new-email" placeholder="email@..."></td>
<td><input class="form-input" id="ct-new-phone" placeholder="+57..."></td>
<td><input class="form-input" id="ct-new-whatsapp" placeholder="+57..."></td>
<td>
<select class="form-input-select" id="ct-new-pref">
<option value="EMAIL">EMAIL</option>
<option value="WHATSAPP">WHATSAPP</option>
<option value="SMS">SMS</option>
</select>
</td>
<td><button class="chart-row-btn" id="btn-contact-add">ADD</button></td>
</tr>
</tfoot>
</table>
<div id="contacts-status" class="save-status" style="margin-top:8px"></div>
</div>
<div class="modal-footer">
<button class="btn-modal-secondary" id="btn-close-contacts2">CLOSE</button>
</div>
</div>
<!-- LAMP CATALOG -->
<div id="modal-lamps" class="modal modal-wide hidden">
<div class="modal-header">
<span class="modal-title">LAMP CATALOG — Battery thresholds derived from V min/max</span>
<button class="modal-close" id="btn-close-lamps">&times;</button>
</div>
<div class="modal-body">
<div style="font-size:0.72rem;color:var(--text-muted);margin-bottom:10px">
Each row defines a lamp model. <strong>V min</strong> = nominal discharged battery voltage (e.g. 12.2 V).
<strong>V max</strong> = nominal fully-charged voltage (e.g. 12.8 V). Aids assigned to this lamp get
their battery WARN / ALARM thresholds computed automatically:<br>
<code style="color:var(--accent)">warn = vmin + (vmax vmin) × 0.20</code> &nbsp;·&nbsp;
<code style="color:var(--accent)">alarm = vmin + (vmax vmin) × 0.10</code>
</div>
<table class="chart-table" id="lamps-table">
<thead><tr>
<th>Manufacturer</th><th>Model</th><th># Lamps</th>
<th title="Nominal voltage when fully discharged">V min nom.</th>
<th title="Nominal voltage when fully charged">V max nom.</th>
<th>WARN</th><th>ALARM</th>
<th>Notes</th><th></th>
</tr></thead>
<tbody id="lamps-body"></tbody>
<tfoot>
<tr id="lamps-newrow">
<td><input class="form-input" id="lp-new-mfr" placeholder="e.g. Tideland"></td>
<td><input class="form-input" id="lp-new-model" placeholder="e.g. MaxLumen 200"></td>
<td><input class="form-input" id="lp-new-count" type="number" value="1" style="width:60px"></td>
<td><input class="form-input" id="lp-new-vmin" type="number" step="0.1" placeholder="12.2" style="width:70px"></td>
<td><input class="form-input" id="lp-new-vmax" type="number" step="0.1" placeholder="12.8" style="width:70px"></td>
<td colspan="2" style="font-size:0.7rem;color:var(--text-muted)" id="lp-new-preview"></td>
<td><input class="form-input" id="lp-new-notes" placeholder="optional"></td>
<td><button class="chart-row-btn" id="btn-lamp-add">ADD</button></td>
</tr>
</tfoot>
</table>
<div id="lamps-status" class="save-status" style="margin-top:8px"></div>
</div>
<div class="modal-footer">
<button class="btn-modal-secondary" id="btn-close-lamps2">CLOSE</button>
</div>
</div>
<!-- DVR — AIS TRACK HISTORY ─────────────────────────────────────────── -->
<div id="modal-track-history" class="modal modal-wide hidden" style="max-width:820px">
<div class="modal-header">
<span class="modal-title">AIS TRACK HISTORY — DVR Replay</span>
<button class="modal-close" id="btn-close-track-history">&times;</button>
</div>
<div class="modal-body">
<div style="display:flex;gap:10px;margin-bottom:14px;align-items:flex-end;flex-wrap:wrap">
<div class="form-field" style="flex:1;min-width:160px">
<label class="form-label">MMSI</label>
<input class="form-input" id="dvr-mmsi" placeholder="e.g. 123456789">
</div>
<div class="form-field">
<label class="form-label">Date From</label>
<input class="form-input" id="dvr-from" type="date">
</div>
<div class="form-field">
<label class="form-label">Date To</label>
<input class="form-input" id="dvr-to" type="date">
</div>
<div class="form-field">
<label class="form-label">Source</label>
<select class="form-input-select" id="dvr-source">
<option value="vessel">Vessel (AIS)</option>
<option value="aton">AtoN (Type 21)</option>
</select>
</div>
<button class="btn-modal-primary" id="btn-dvr-load" style="padding:5px 14px;margin-bottom:0">LOAD TRACK</button>
</div>
<!-- Track stats bar -->
<div id="dvr-stats" style="font-size:0.72rem;color:var(--text-muted);margin-bottom:8px;display:none">
<span id="dvr-stats-text"></span>
<button class="chart-row-btn" id="btn-dvr-show-map" style="margin-left:10px">SHOW ON MAP</button>
<button class="chart-row-btn" id="btn-dvr-csv" style="margin-left:4px">EXPORT CSV</button>
</div>
<!-- DVR playback controls (visible once track loaded) -->
<div id="dvr-controls" style="display:none;background:#0d1b2a;border:1px solid #1e3a5f;border-radius:4px;padding:10px;margin-bottom:10px">
<div style="display:flex;align-items:center;gap:10px;flex-wrap:wrap">
<button class="chart-row-btn" id="btn-dvr-play" title="Play">&#9654;</button>
<button class="chart-row-btn" id="btn-dvr-pause" title="Pause">&#9646;&#9646;</button>
<button class="chart-row-btn" id="btn-dvr-stop" title="Stop / Reset">&#9632;</button>
<label class="form-label" style="margin:0 4px 0 8px">Speed</label>
<select class="form-input-select" id="dvr-speed" style="width:80px">
<option value="1">1×</option>
<option value="5">5×</option>
<option value="20" selected>20×</option>
<option value="60">60×</option>
<option value="300">300×</option>
</select>
<div style="flex:1;min-width:160px">
<input type="range" id="dvr-slider" min="0" value="0" style="width:100%;accent-color:var(--accent)">
</div>
<span id="dvr-timestamp" class="mono" style="font-size:0.7rem;color:var(--accent);min-width:140px">--:--:-- UTC</span>
</div>
<div id="dvr-position" style="font-size:0.7rem;color:var(--text-muted);margin-top:6px">
<span id="dvr-lat">LAT --</span> &nbsp; <span id="dvr-lon">LON --</span>
&nbsp;·&nbsp; <span id="dvr-sog">SOG --</span> kn
&nbsp;·&nbsp; <span id="dvr-cog">COG --</span>°
</div>
</div>
<!-- Track table -->
<div id="dvr-body" style="max-height:280px;overflow-y:auto">
<div style="color:var(--text-muted);font-size:0.75rem;padding:20px 0;text-align:center">
Enter an MMSI and date range, then press LOAD TRACK.
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn-modal-secondary" id="btn-close-track-history2">CLOSE</button>
</div>
</div>
<!-- ORGANIZATION MANAGEMENT (Ports, Companies, Buoy Ownership) ────────── -->
<div id="modal-org" class="modal modal-wide hidden" style="max-width:900px">
<div class="modal-header">
<span class="modal-title">ORGANIZATION — Ports, Companies &amp; Buoy Ownership</span>
<button class="modal-close" id="btn-close-org">&times;</button>
</div>
<div class="modal-body">
<div class="stab-bar" style="margin-bottom:14px">
<button class="stab active" data-otab="otab-ports">PORTS</button>
<button class="stab" data-otab="otab-companies">COMPANIES</button>
<button class="stab" data-otab="otab-ownership">BUOY OWNERSHIP</button>
</div>
<!-- TAB: PORTS -->
<div id="otab-ports" class="otab-panel">
<div style="font-size:0.72rem;color:var(--text-muted);margin-bottom:10px">
Ports are used to set the default map view for each company's users on login.
</div>
<table class="chart-table" id="org-ports-table">
<thead><tr><th>Name</th><th>Center</th><th>Zoom</th><th>Chart</th><th>Status</th><th></th></tr></thead>
<tbody id="org-ports-body"></tbody>
</table>
<div style="margin-top:10px;display:flex;gap:8px;flex-wrap:wrap;align-items:flex-end">
<input class="form-input" id="op-name" placeholder="Port name" style="width:150px">
<input class="form-input" id="op-lat" placeholder="Lat" type="number" step="0.0001" style="width:100px">
<input class="form-input" id="op-lon" placeholder="Lon" type="number" step="0.0001" style="width:100px">
<input class="form-input" id="op-zoom" placeholder="Zoom (12)" type="number" step="0.5" style="width:80px">
<input class="form-input" id="op-chart" placeholder="Chart folder (opt.)" style="width:160px">
<button class="btn-modal-primary" id="btn-port-add" style="padding:5px 12px">ADD PORT</button>
</div>
<div id="org-ports-status" class="save-status" style="margin-top:8px"></div>
</div>
<!-- TAB: COMPANIES -->
<div id="otab-companies" class="otab-panel hidden">
<table class="chart-table" id="org-companies-table">
<thead><tr><th>Company</th><th>Home Port</th><th>Email</th><th>Phone</th><th>Status</th><th></th></tr></thead>
<tbody id="org-companies-body"></tbody>
</table>
<div style="margin-top:10px;display:flex;gap:8px;flex-wrap:wrap;align-items:flex-end">
<input class="form-input" id="oc-name" placeholder="Company name" style="width:200px">
<select class="form-input-select" id="oc-port" style="width:160px">
<option value="">— Select port —</option>
</select>
<input class="form-input" id="oc-email" placeholder="Contact email" style="width:180px">
<input class="form-input" id="oc-phone" placeholder="Phone" style="width:130px">
<button class="btn-modal-primary" id="btn-company-add" style="padding:5px 12px">ADD COMPANY</button>
</div>
<div id="org-companies-status" class="save-status" style="margin-top:8px"></div>
</div>
<!-- TAB: BUOY OWNERSHIP -->
<div id="otab-ownership" class="otab-panel hidden">
<div style="display:flex;gap:10px;margin-bottom:10px;align-items:flex-end">
<div class="form-field" style="flex:1">
<label class="form-label">Filter by Company</label>
<select class="form-input-select" id="ow-filter-company">
<option value="">— All companies —</option>
</select>
</div>
<button class="chart-row-btn" id="btn-ow-load">LOAD</button>
</div>
<table class="chart-table" id="org-ownership-table">
<thead><tr><th>Company</th><th>Aid Name</th><th>MMSI</th><th>Notes</th><th></th></tr></thead>
<tbody id="org-ownership-body"></tbody>
</table>
<div style="margin-top:10px;display:flex;gap:8px;flex-wrap:wrap;align-items:flex-end">
<select class="form-input-select" id="ow-company-sel" style="width:200px">
<option value="">— Company —</option>
</select>
<input class="form-input" id="ow-aid-id" placeholder="Aid ID (UUID)" style="width:230px">
<input class="form-input" id="ow-mmsi" placeholder="or MMSI" style="width:130px">
<input class="form-input" id="ow-notes" placeholder="Notes (opt.)" style="width:150px">
<button class="btn-modal-primary" id="btn-ow-assign" style="padding:5px 12px">ASSIGN</button>
</div>
<div id="org-ownership-status" class="save-status" style="margin-top:8px"></div>
</div>
</div>
<div class="modal-footer">
<button class="btn-modal-secondary" id="btn-close-org2">CLOSE</button>
</div>
</div>
</div><!-- /modal-overlay -->
<script src="https://cdn.jsdelivr.net/npm/ol@v9.2.4/dist/ol.js"></script>
<script src="js/ports.js"></script>
<script src="js/auth.js"></script>
<script src="js/map.js"></script>
<script src="js/websocket.js"></script>
<script src="js/menu.js"></script>
<script src="js/dvr.js"></script>
<script src="js/org.js"></script>
</body>
</html>