// aero-alerts.jsx + aero-api.jsx — Alerts page and API/Developers page // ───────────────────────────────────────────────────────────────────── // PAGE: ALERTS // ───────────────────────────────────────────────────────────────────── function PageAlerts({ lang }) { const t = window.WX.T[lang]; const [filter, setFilter] = useState("all"); // all | warning | watch | advisory const alerts = [ { id: "BR-RS-2026-0518", level: "warning", title_pt: "Chuvas intensas com risco de alagamentos", title_en: "Heavy rain with flooding risk", area_pt: "Mesorregião Centro-Ocidental, Rio Grande do Sul", area_en: "Central-Western Rio Grande do Sul", desc_pt: "Acumulados entre 30 e 60 mm em 24 horas com alta probabilidade de descargas atmosféricas. Risco de alagamentos em áreas urbanas, deslizamentos em encostas e elevação rápida do nível dos rios.", desc_en: "30 to 60 mm in 24 hours with high probability of lightning strikes. Risk of urban flooding, landslides on slopes, and rapid river rise.", issued: "2026-05-26T06:00", expires: "2026-05-26T22:00", issuer: "INMET", areas: ["RS", "SC"], severity: 3, certainty: 0.92, }, { id: "BR-SC-2026-0317", level: "watch", title_pt: "Vendaval costeiro", title_en: "Coastal wind advisory", area_pt: "Faixa litorânea sul de Santa Catarina", area_en: "Southern coast of Santa Catarina", desc_pt: "Rajadas entre 60 e 80 km/h vindas do quadrante sudeste. Risco de queda de árvores e destelhamento de estruturas frágeis. Navegação restrita para pequenas embarcações.", desc_en: "Gusts 60–80 km/h from the southeast. Risk of fallen trees and damage to fragile structures. Small craft advisory in effect.", issued: "2026-05-26T08:30", expires: "2026-05-26T18:00", issuer: "Marinha · DHN", areas: ["SC"], severity: 2, certainty: 0.78, }, { id: "BR-MG-2026-0226", level: "advisory", title_pt: "Baixa umidade do ar", title_en: "Low humidity advisory", area_pt: "Triângulo Mineiro e Alto Paranaíba", area_en: "Triângulo Mineiro and Alto Paranaíba", desc_pt: "Umidade relativa do ar entre 12% e 20% durante a tarde. Risco de incêndios florestais elevado. Manter hidratação e evitar atividade física entre 12h e 16h.", desc_en: "Relative humidity between 12% and 20% during the afternoon. High wildfire risk. Stay hydrated and avoid physical activity between 12:00 and 16:00.", issued: "2026-05-26T05:00", expires: "2026-05-27T00:00", issuer: "INMET", areas: ["MG", "GO"], severity: 1, certainty: 0.85, }, { id: "BR-AM-2026-0119", level: "advisory", title_pt: "Chuvas convectivas", title_en: "Convective showers", area_pt: "Amazonas e Roraima", area_en: "Amazonas and Roraima", desc_pt: "Aguaceiros isolados com possibilidade de descargas atmosféricas. Acumulados localizados podem superar 40 mm em 6 horas.", desc_en: "Isolated downpours with possibility of lightning. Local accumulations may exceed 40 mm in 6 hours.", issued: "2026-05-26T04:00", expires: "2026-05-26T20:00", issuer: "CPTEC", areas: ["AM", "RR"], severity: 1, certainty: 0.71, }, ]; const filtered = alerts.filter(a => filter === "all" || a.level === filter); return (
{/* HEADER */}
{lang === "pt" ? "Início" : "Home"} {" / "}{lang === "pt" ? "Alertas" : "Alerts"}

{lang === "pt" ? "Avisos & alertas ativos" : "Active alerts & advisories"}

a.level === "warning").length} label={lang === "pt" ? "Alertas" : "Warnings"} color={AERO.danger} /> a.level === "watch").length} label={lang === "pt" ? "Atenção" : "Watches"} color={AERO.warm} /> a.level === "advisory").length} label={lang === "pt" ? "Avisos" : "Advisories"} color={AERO.accent} />
{[ ["all", lang === "pt" ? "Todos" : "All"], ["warning", lang === "pt" ? "Alerta" : "Warning"], ["watch", lang === "pt" ? "Atenção" : "Watch"], ["advisory", lang === "pt" ? "Aviso" : "Advisory"], ].map(([k, l]) => ( ))}
{/* ALERTS LIST + MAP */}
{filtered.map(a => )}
); } function StatBlock({ value, label, color }) { return (
{value}
{label}
); } function BigAlertCard({ alert: a, lang }) { const accent = a.level === "warning" ? AERO.danger : a.level === "watch" ? AERO.warm : AERO.accent; const levelLabel = a.level === "warning" ? (lang === "pt" ? "Alerta" : "Warning") : a.level === "watch" ? (lang === "pt" ? "Atenção" : "Watch") : (lang === "pt" ? "Aviso" : "Advisory"); const title = lang === "pt" ? a.title_pt : a.title_en; const area = lang === "pt" ? a.area_pt : a.area_en; const desc = lang === "pt" ? a.desc_pt : a.desc_en; return (
{levelLabel} {a.id} {a.areas.map(ar => ( {ar} ))}

{title}

{area} · {a.issuer}

{desc}

{lang === "pt" ? "Detalhes →" : "Details →"}
); } function Pair({ label, value, valColor }) { return (
{label}
{value}
); } // Stylized Brazil map showing affected states. function AlertsMap({ lang }) { // affected: RS, SC, MG, GO, AM, RR const affected = { RS: { color: AERO.danger, label: lang === "pt" ? "Alerta" : "Warning" }, SC: { color: AERO.warm, label: lang === "pt" ? "Atenção" : "Watch" }, MG: { color: AERO.accent, label: lang === "pt" ? "Aviso" : "Advisory" }, GO: { color: AERO.accent, label: lang === "pt" ? "Aviso" : "Advisory" }, AM: { color: AERO.accent, label: lang === "pt" ? "Aviso" : "Advisory" }, RR: { color: AERO.accent, label: lang === "pt" ? "Aviso" : "Advisory" }, }; return (
{/* abstract Brazil */} {/* approximate state regions (very simplified) */} {/* RS — bottom */} {/* SC — small NE of RS */} {/* MG + GO */} {/* AM + RR */} {/* outline overlay */} {/* state labels */} {Object.entries({ RS: [180, 312], SC: [248, 290], MG: [220, 184], GO: [160, 184], AM: [140, 105], RR: [170, 70], }).map(([s, [x, y]]) => ( {s} ))}
); } function Legend({ swatch, label }) { return (
{label}
); } // ───────────────────────────────────────────────────────────────────── // PAGE: API / DEVELOPERS // ───────────────────────────────────────────────────────────────────── function PageAPI({ lang }) { const [endpoint, setEndpoint] = useState("/weather"); const [tab, setTab] = useState("curl"); // curl | js | python | response return (
{/* HEADER */}
{lang === "pt" ? "Início" : "Home"} {" / "}API

{lang === "pt" ? "Uma API meteorológica. Sem firulas." : "One meteorological API. No frills."}

{lang === "pt" ? "REST sobre HTTPS. JSON em entrada e saída. Latência típica de 230ms. Cobertura global com 847 estações em tempo real, 14 modelos numéricos integrados, e histórico desde 1991. Plano free com 10.000 requisições por dia." : "REST over HTTPS. JSON in, JSON out. Typical 230ms latency. Global coverage with 847 real-time stations, 14 integrated numerical models, and history back to 1991. Free plan: 10,000 requests/day."}

$ {lang === "pt" ? "começar agora" : "get started"}
curl https://api.aerograma.pro/v1/weather?lat=-29.69&lon=-53.84
{/* ENDPOINT TRY-IT */} {lang === "pt" ? "Endpoints" : "Endpoints"}
{/* sidebar */}
{[ ["GET", "/weather", lang === "pt" ? "Estado atual + previsão" : "Current + forecast"], ["GET", "/forecast", lang === "pt" ? "Previsão estendida" : "Extended forecast"], ["GET", "/hourly", lang === "pt" ? "Série horária" : "Hourly series"], ["GET", "/radar", lang === "pt" ? "Tiles de radar" : "Radar tiles"], ["GET", "/satellite", lang === "pt" ? "Imagens GOES-16" : "GOES-16 imagery"], ["GET", "/alerts", lang === "pt" ? "Alertas oficiais" : "Official alerts"], ["GET", "/stations", lang === "pt" ? "Rede de estações" : "Station network"], ["GET", "/models", lang === "pt" ? "Saídas brutas de modelos" : "Raw model output"], ["POST", "/webhooks", lang === "pt" ? "Inscrever em eventos" : "Subscribe to events"], ].map(([m, path, desc]) => ( ))}
{/* content */}
{/* Pricing strip */} {lang === "pt" ? "Planos" : "Plans"}
); } function EndpointDoc({ lang, endpoint, tab, setTab }) { const examples = { curl: `curl -X GET "https://api.aerograma.pro/v1/weather" \\ -H "Authorization: Bearer $AEROGRAMA_KEY" \\ -G --data-urlencode "lat=-29.69" \\ --data-urlencode "lon=-53.84" \\ --data-urlencode "dias=7"`, js: `import { Aerograma } from "@aerograma/sdk"; const ag = new Aerograma(process.env.AEROGRAMA_KEY); const data = await ag.weather({ lat: -29.69, lon: -53.84, dias: 7, }); console.log(data.current_complete.temperature_2m); // 14.4`, python: `from aerograma import Client ag = Client(api_key=os.environ["AEROGRAMA_KEY"]) data = ag.weather(lat=-29.69, lon=-53.84, dias=7) print(data.current_complete.temperature_2m) # 14.4`, response: `{ "latitude": -29.701231, "longitude": -53.874695, "elevation": 77, "timezone": "America/Sao_Paulo", "current_complete": { "time": "2026-05-26T08:30", "temperature_2m": 14.4, "apparent_temperature": 15.2, "relative_humidity_2m": 99, "surface_pressure": 1010.4, "wind_speed_10m": 4.1, "wind_direction_10m": 268, "weathercode": 55, "weathercode_desc": { "pt": "Garoa intensa", "en": "Dense drizzle" } }, "forecast": [ … 7 days … ], "hourly": { … 24 hours of fields … } }`, }; return (
GET https://api.aerograma.pro/v1{endpoint}

{lang === "pt" ? "Estado atual + previsão" : "Current state + forecast"}

{lang === "pt" ? "Retorna observações de superfície em tempo real, previsão horária para 24h e previsão diária para até 15 dias para qualquer coordenada do globo." : "Returns real-time surface observations, hourly forecast for 24h, and daily forecast up to 15 days for any global coordinate."}

{/* Params */}
{lang === "pt" ? "Parâmetros" : "Parameters"}
{[ ["lat", "float", true, lang === "pt" ? "Latitude (-90 ≤ lat ≤ 90)" : "Latitude (-90 ≤ lat ≤ 90)"], ["lon", "float", true, lang === "pt" ? "Longitude (-180 ≤ lon ≤ 180)" : "Longitude (-180 ≤ lon ≤ 180)"], ["dias", "int", false, lang === "pt" ? "Número de dias de previsão (1–15). Padrão: 7" : "Forecast days (1–15). Default: 7"], ["lang", "string", false, lang === "pt" ? "Idioma dos textos (pt | en). Padrão: pt" : "Description language (pt | en). Default: pt"], ["units", "string", false, lang === "pt" ? "metric | imperial. Padrão: metric" : "metric | imperial. Default: metric"], ].map(([name, type, required, desc]) => (
{name} {type} {required ? (lang === "pt" ? "obrigatório" : "required") : (lang === "pt" ? "opcional" : "optional")} {desc}
))}
{/* Code tabs */}
{[ ["curl", "cURL"], ["js", "JavaScript"], ["python", "Python"], ["response", "Response"], ].map(([k, l]) => ( ))}
          {examples[tab]}
        
); } function PriceCard({ tier, price, currency, reqs, features, highlight, lang }) { return (
{tier}
{currency}{price}
{reqs} · {lang === "pt" ? "requisições" : "requests"}
{features.map(f => (
{f}
))}
{lang === "pt" ? "Começar" : "Get started"}
); } Object.assign(window, { PageAlerts, PageAPI });