File size: 4,695 Bytes
c528423
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/* global React */

function CodeBlock({ lang, code, t }) {
  return (
    <div className="code-block">
      <div className="code-head">
        <span className="lang">{lang}</span>
        <button
          className="copy-btn"
          onClick={(e) => {
            navigator.clipboard.writeText(code);
            const btn = e.currentTarget;
            btn.textContent = t("docs_copied");
            setTimeout(() => { btn.textContent = t("docs_copy"); }, 1400);
          }}
        >{t("docs_copy")}</button>
      </div>
      <pre><code>{code}</code></pre>
    </div>
  );
}

const PY_EXAMPLE = `import requests

r = requests.post(
    "/predict",
    json={
        "latitude": 48.8566,
        "longitude": 2.3522,
        "altitude_km": 11.6
    },
)

data = r.json()
print(f"Dose: {data['dose_usvh']} µSv/h ({data['risk_level']})")
`;

const CURL_EXAMPLE = `curl -X POST /predict \\
  -H "Content-Type: application/json" \\
  -d '{
    "latitude": 48.8566,
    "longitude": 2.3522,
    "altitude_km": 11.6
  }'
`;

const JSON_EXAMPLE = `{
  "dose_usvh": 3.95,
  "lower_bound": 3.48,
  "upper_bound": 4.42,
  "risk_level": "moderate",
  "kp_current": 2.7,
  "timestamp": "2026-05-09T14:23:00Z"
}
`;

function DocsPage({ t }) {
  return (
    <>
      <section className="hero" style={{ paddingBottom: 32 }}>
        <h1 style={{ fontSize: "clamp(34px, 4.6vw, 52px)" }}>{t("docs_title")}</h1>
        <p className="lead">{t("docs_lead")}</p>
      </section>

      <div className="docs">
        <div className="docs-card">
          <div className="endpoint">
            <span className="method">POST</span>
            <span className="path">/predict</span>
          </div>

          <h3 className="docs-h3">{t("docs_h_params")}</h3>
          <table className="param-table">
            <thead>
              <tr>
                <th>{t("docs_th_field")}</th>
                <th>{t("docs_th_type")}</th>
                <th>{t("docs_th_desc")}</th>
              </tr>
            </thead>
            <tbody>
              <tr><td><code>latitude</code></td><td>float</td><td>{t("docs_p_lat")}</td></tr>
              <tr><td><code>longitude</code></td><td>float</td><td>{t("docs_p_lon")}</td></tr>
              <tr><td><code>altitude_km</code></td><td>float</td><td>{t("docs_p_alt")}</td></tr>
            </tbody>
          </table>

          <h3 className="docs-h3">{t("docs_h_response")}</h3>
          <table className="param-table">
            <thead>
              <tr>
                <th>{t("docs_th_field")}</th>
                <th>{t("docs_th_type")}</th>
                <th>{t("docs_th_desc")}</th>
              </tr>
            </thead>
            <tbody>
              <tr><td><code>dose_usvh</code></td><td>float</td><td>{t("docs_r_dose")}</td></tr>
              <tr><td><code>lower_bound</code></td><td>float</td><td>{t("docs_r_low")}</td></tr>
              <tr><td><code>upper_bound</code></td><td>float</td><td>{t("docs_r_high")}</td></tr>
              <tr><td><code>risk_level</code></td><td>string</td><td>{t("docs_r_risk")}</td></tr>
              <tr><td><code>kp_current</code></td><td>float</td><td>{t("docs_r_kp")}</td></tr>
              <tr><td><code>timestamp</code></td><td>string</td><td>{t("docs_r_ts")}</td></tr>
            </tbody>
          </table>
        </div>

        <h3 className="docs-h3" style={{ marginTop: 8 }}>{t("docs_h_examples")}</h3>
        <div className="docs-grid-2">
          <CodeBlock lang="Python" code={PY_EXAMPLE} t={t} />
          <CodeBlock lang="cURL" code={CURL_EXAMPLE} t={t} />
        </div>

        <CodeBlock lang="JSON" code={JSON_EXAMPLE} t={t} />

        <a className="github-link" href="https://github.com/penumbra-aero/predict" target="_blank" rel="noopener">
          <span className="gh-mark" aria-hidden="true">
            <svg viewBox="0 0 16 16" width="18" height="18" fill="currentColor"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
          </span>
          <span>{t("docs_github")}</span>
          <span className="arrow-ext" aria-hidden="true"></span>
        </a>
      </div>
    </>
  );
}

window.DocsPage = DocsPage;