astrogators-shared-ui 0.16.3 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +11 -4
- package/dist/index.js +228 -198
- package/dist/src/contexts/AuthContext.d.ts +16 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/services/account.d.ts +21 -0
- package/dist/src/types/index.d.ts +1 -1
- package/dist/src/types/user.d.ts +24 -0
- package/package.json +8 -6
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 psytor
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# astrogators-shared-ui
|
|
2
2
|
|
|
3
3
|
Shared React components, auth, and API client for the Astrogator's Table
|
|
4
|
-
frontends (`astrogators-hub`, `mod-ledger-ui`, `nightwatcher-ui
|
|
5
|
-
to the public npm registry as
|
|
4
|
+
frontends (`astrogators-hub`, `mod-ledger-ui`, `nightwatcher-ui`,
|
|
5
|
+
`navicharts-ui`). Published to the public npm registry as
|
|
6
|
+
`astrogators-shared-ui` (unscoped).
|
|
6
7
|
|
|
7
8
|
> The git repo lives under `psytor/astrogators-shared-ui` on GitHub, but the
|
|
8
9
|
> package itself is published to **npmjs.org**, not GitHub Packages. No
|
|
@@ -177,9 +178,14 @@ const result = await apiClient.post('/api/v1/mod-ledger/evaluate/123456789', {
|
|
|
177
178
|
|
|
178
179
|
The client:
|
|
179
180
|
- injects the access token into `Authorization`
|
|
180
|
-
-
|
|
181
|
-
|
|
181
|
+
- proactively refreshes before a request goes out if the access token is
|
|
182
|
+
expired or expiring within 30s (decoded client-side), and reactively on a
|
|
183
|
+
`401` from the resource server — both via `/api/v1/auth/refresh`, retrying
|
|
184
|
+
the original request once
|
|
182
185
|
- calls `onUnauthorized` if refresh fails
|
|
186
|
+
- retries a `502`/`503`/`504` response (idempotent methods only) or a thrown
|
|
187
|
+
`fetch` (any method, since nothing reached the server) a couple of times
|
|
188
|
+
with a short backoff, to ride out a backend container swap mid-deploy
|
|
183
189
|
|
|
184
190
|
Endpoints are written **without** the service prefix — the prefix lives in
|
|
185
191
|
the configured `baseURL`.
|
|
@@ -254,6 +260,7 @@ Sci-fi cut-corner effect, available as utility classes or via `Card`:
|
|
|
254
260
|
npm install
|
|
255
261
|
npm run build # tsc && vite build → dist/
|
|
256
262
|
npm run type-check # tsc --noEmit
|
|
263
|
+
npm test # vitest run — logic tests in tests/ (not visual)
|
|
257
264
|
```
|
|
258
265
|
|
|
259
266
|
There is no `dev` server worth running (this is a library, not an app).
|
package/dist/index.js
CHANGED
|
@@ -140,9 +140,9 @@ var _ = [
|
|
|
140
140
|
x(e), w(t);
|
|
141
141
|
}, D = () => {
|
|
142
142
|
S(), T();
|
|
143
|
-
}, O = () => !!b(), ee = "",
|
|
144
|
-
ee = e.baseURL,
|
|
145
|
-
}, j = () =>
|
|
143
|
+
}, O = () => !!b(), ee = "", te, k = null, A = (e) => {
|
|
144
|
+
ee = e.baseURL, te = e.onUnauthorized;
|
|
145
|
+
}, j = () => k || (k = (async () => {
|
|
146
146
|
let e = C();
|
|
147
147
|
if (!e) throw Error("No refresh token available");
|
|
148
148
|
let t = await fetch(`${ee}/api/v1/auth/refresh`, {
|
|
@@ -150,22 +150,22 @@ var _ = [
|
|
|
150
150
|
headers: { "Content-Type": "application/json" },
|
|
151
151
|
body: JSON.stringify({ refresh_token: e })
|
|
152
152
|
});
|
|
153
|
-
if (!t.ok) throw D(),
|
|
153
|
+
if (!t.ok) throw D(), te?.(), Error("Token refresh failed");
|
|
154
154
|
let n = await t.json();
|
|
155
155
|
return E(n.access_token, n.refresh_token), n.access_token;
|
|
156
156
|
})().finally(() => {
|
|
157
|
-
|
|
158
|
-
}),
|
|
157
|
+
k = null;
|
|
158
|
+
}), k), ne = 30, M = [700, 1500], N = /* @__PURE__ */ new Set([
|
|
159
159
|
502,
|
|
160
160
|
503,
|
|
161
161
|
504
|
|
162
|
-
]),
|
|
162
|
+
]), P = (e) => {
|
|
163
163
|
let t = (e ?? "GET").toUpperCase();
|
|
164
164
|
return t === "GET" || t === "HEAD" || t === "OPTIONS";
|
|
165
|
-
},
|
|
166
|
-
let n =
|
|
165
|
+
}, F = (e) => e == null || typeof e == "string", re = (e) => new Promise((t) => setTimeout(t, e)), I = async (e, t) => {
|
|
166
|
+
let n = P(t.method) && F(t.body), r = F(t.body), i;
|
|
167
167
|
for (let a = 0; a <= M.length; a++) {
|
|
168
|
-
a > 0 && await
|
|
168
|
+
a > 0 && await re(M[a - 1]);
|
|
169
169
|
let o = a < M.length;
|
|
170
170
|
try {
|
|
171
171
|
let r = await fetch(e, t);
|
|
@@ -177,39 +177,39 @@ var _ = [
|
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
throw i ?? /* @__PURE__ */ Error("fetchWithRetry: retries exhausted");
|
|
180
|
-
},
|
|
180
|
+
}, ie = (e) => {
|
|
181
181
|
try {
|
|
182
182
|
let t = e.split(".")[1].replace(/-/g, "+").replace(/_/g, "/"), { exp: n } = JSON.parse(atob(t));
|
|
183
183
|
return typeof n == "number" && Date.now() / 1e3 >= n - ne;
|
|
184
184
|
} catch {
|
|
185
185
|
return !1;
|
|
186
186
|
}
|
|
187
|
-
},
|
|
187
|
+
}, ae = async (e, t = {}) => {
|
|
188
188
|
let n = b();
|
|
189
|
-
if (n &&
|
|
189
|
+
if (n && ie(n)) try {
|
|
190
190
|
n = await j();
|
|
191
191
|
} catch {
|
|
192
192
|
n = b();
|
|
193
193
|
}
|
|
194
194
|
let r = { ...t.headers };
|
|
195
195
|
n && (r.Authorization = `Bearer ${n}`);
|
|
196
|
-
let i = await
|
|
196
|
+
let i = await I(e, {
|
|
197
197
|
...t,
|
|
198
198
|
headers: r
|
|
199
199
|
});
|
|
200
200
|
if (i.status !== 401 || !n) return i;
|
|
201
201
|
try {
|
|
202
|
-
return r.Authorization = `Bearer ${await j()}`, await
|
|
202
|
+
return r.Authorization = `Bearer ${await j()}`, await I(e, {
|
|
203
203
|
...t,
|
|
204
204
|
headers: r
|
|
205
205
|
});
|
|
206
206
|
} catch {
|
|
207
207
|
return i;
|
|
208
208
|
}
|
|
209
|
-
},
|
|
209
|
+
}, oe = class {
|
|
210
210
|
baseURL;
|
|
211
211
|
constructor(e) {
|
|
212
|
-
this.baseURL = e.baseURL,
|
|
212
|
+
this.baseURL = e.baseURL, A({
|
|
213
213
|
baseURL: e.baseURL,
|
|
214
214
|
onUnauthorized: e.onUnauthorized
|
|
215
215
|
});
|
|
@@ -218,7 +218,7 @@ var _ = [
|
|
|
218
218
|
let n = {
|
|
219
219
|
"Content-Type": "application/json",
|
|
220
220
|
...t.headers
|
|
221
|
-
}, r = await
|
|
221
|
+
}, r = await ae(`${this.baseURL}${e}`, {
|
|
222
222
|
...t,
|
|
223
223
|
headers: n
|
|
224
224
|
});
|
|
@@ -268,53 +268,57 @@ var _ = [
|
|
|
268
268
|
method: "DELETE"
|
|
269
269
|
});
|
|
270
270
|
}
|
|
271
|
-
},
|
|
272
|
-
|
|
273
|
-
},
|
|
271
|
+
}, L, se = (e) => {
|
|
272
|
+
L = new oe(e);
|
|
273
|
+
}, ce = async (e) => {
|
|
274
|
+
let t = await L.patch("/api/v1/users/me", e);
|
|
275
|
+
return t.tokens && E(t.tokens.access_token, t.tokens.refresh_token), t;
|
|
276
|
+
}, le = async () => (await L.post("/api/v1/auth/logout-all")).message, R = "astrogators_ally_codes", ue = "astrogators_selected_ally_code", z = () => {
|
|
274
277
|
try {
|
|
275
|
-
let e = localStorage.getItem(
|
|
278
|
+
let e = localStorage.getItem(R);
|
|
276
279
|
return e ? JSON.parse(e) : [];
|
|
277
280
|
} catch (e) {
|
|
278
281
|
return console.error("Failed to read ally codes from localStorage:", e), [];
|
|
279
282
|
}
|
|
280
283
|
}, de = (e) => {
|
|
281
284
|
try {
|
|
282
|
-
let t =
|
|
285
|
+
let t = z();
|
|
283
286
|
if (t.some((t) => t.ally_code === e.ally_code)) return;
|
|
284
|
-
t.push(e), localStorage.setItem(
|
|
287
|
+
t.push(e), localStorage.setItem(R, JSON.stringify(t));
|
|
285
288
|
} catch (e) {
|
|
286
289
|
console.error("Failed to save ally code to localStorage:", e);
|
|
287
290
|
}
|
|
288
291
|
}, fe = (e) => {
|
|
289
292
|
try {
|
|
290
|
-
let t =
|
|
291
|
-
localStorage.setItem(
|
|
293
|
+
let t = z().filter((t) => t.ally_code !== e);
|
|
294
|
+
localStorage.setItem(R, JSON.stringify(t));
|
|
292
295
|
} catch (e) {
|
|
293
296
|
console.error("Failed to remove ally code from localStorage:", e);
|
|
294
297
|
}
|
|
295
298
|
}, pe = (e) => {
|
|
296
299
|
try {
|
|
297
|
-
let t =
|
|
300
|
+
let t = z().map((t) => t.ally_code === e ? {
|
|
298
301
|
...t,
|
|
299
302
|
last_used_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
300
303
|
} : t);
|
|
301
|
-
localStorage.setItem(
|
|
304
|
+
localStorage.setItem(R, JSON.stringify(t));
|
|
302
305
|
} catch (e) {
|
|
303
306
|
console.error("Failed to update ally code last used:", e);
|
|
304
307
|
}
|
|
305
|
-
}, me = () => localStorage.getItem(ue),
|
|
308
|
+
}, me = () => localStorage.getItem(ue), B = (e) => {
|
|
306
309
|
e ? localStorage.setItem(ue, e) : localStorage.removeItem(ue);
|
|
307
310
|
}, he = () => {
|
|
308
|
-
localStorage.removeItem(
|
|
311
|
+
localStorage.removeItem(R), localStorage.removeItem(ue);
|
|
309
312
|
}, ge = t(void 0), _e = ({ children: e, apiBaseUrl: t }) => {
|
|
310
313
|
let [n, i] = s(null), [o, c] = s(!0), [u, d] = s(!0), [f, p] = s(!0), [m, h] = s([]), [g, _] = s(null), [v, y] = s(!1), [b, x] = s({
|
|
311
314
|
show: !1,
|
|
312
315
|
localStorageCodes: []
|
|
313
316
|
});
|
|
314
|
-
|
|
317
|
+
se({ baseURL: t }), a(() => {
|
|
315
318
|
(async () => {
|
|
316
319
|
try {
|
|
317
|
-
|
|
320
|
+
let e = await L.get("/api/v1/config/features");
|
|
321
|
+
d(e.auth_enabled);
|
|
318
322
|
} catch (e) {
|
|
319
323
|
console.error("Failed to fetch features:", e), d(!0);
|
|
320
324
|
} finally {
|
|
@@ -328,7 +332,8 @@ var _ = [
|
|
|
328
332
|
return;
|
|
329
333
|
}
|
|
330
334
|
try {
|
|
331
|
-
|
|
335
|
+
let e = await L.get("/api/v1/users/me");
|
|
336
|
+
i(e);
|
|
332
337
|
} catch (e) {
|
|
333
338
|
console.error("Failed to fetch user:", e), i(null), D();
|
|
334
339
|
} finally {
|
|
@@ -340,122 +345,133 @@ var _ = [
|
|
|
340
345
|
}, [S]);
|
|
341
346
|
let C = async (e) => {
|
|
342
347
|
try {
|
|
343
|
-
let t = await
|
|
344
|
-
E(t.access_token, t.refresh_token)
|
|
348
|
+
let t = await L.post("/api/v1/auth/login", e);
|
|
349
|
+
E(t.access_token, t.refresh_token);
|
|
350
|
+
let n = await L.get("/api/v1/users/me");
|
|
351
|
+
i(n);
|
|
345
352
|
} catch (e) {
|
|
346
353
|
throw console.error("Login failed:", e), e;
|
|
347
354
|
}
|
|
348
355
|
}, w = async (e) => {
|
|
349
356
|
try {
|
|
350
|
-
await
|
|
357
|
+
await L.post("/api/v1/auth/register", e);
|
|
351
358
|
} catch (e) {
|
|
352
359
|
throw console.error("Registration failed:", e), e;
|
|
353
360
|
}
|
|
354
361
|
}, T = () => {
|
|
355
|
-
D(), i(null), h([]), _(null),
|
|
362
|
+
D(), i(null), h([]), _(null), B(null), x({
|
|
356
363
|
show: !1,
|
|
357
364
|
localStorageCodes: []
|
|
358
365
|
});
|
|
359
366
|
}, ee = async () => {
|
|
360
367
|
await S();
|
|
368
|
+
}, te = async () => {
|
|
369
|
+
try {
|
|
370
|
+
await le();
|
|
371
|
+
} finally {
|
|
372
|
+
T();
|
|
373
|
+
}
|
|
361
374
|
}, k = async (e) => {
|
|
375
|
+
let t = await ce(e);
|
|
376
|
+
return i(t), t;
|
|
377
|
+
}, A = async (e) => {
|
|
362
378
|
try {
|
|
363
|
-
return (await
|
|
379
|
+
return (await L.post("/api/v1/auth/forgot-password", e)).message;
|
|
364
380
|
} catch (e) {
|
|
365
381
|
throw console.error("Forgot password failed:", e), e;
|
|
366
382
|
}
|
|
367
|
-
},
|
|
383
|
+
}, j = async (e) => {
|
|
368
384
|
try {
|
|
369
|
-
return (await
|
|
385
|
+
return (await L.post("/api/v1/auth/reset-password", e)).message;
|
|
370
386
|
} catch (e) {
|
|
371
387
|
throw console.error("Reset password failed:", e), e;
|
|
372
388
|
}
|
|
373
|
-
},
|
|
389
|
+
}, ne = async (e) => {
|
|
374
390
|
try {
|
|
375
|
-
return (await
|
|
391
|
+
return (await L.post("/api/v1/auth/resend-verification", e)).message;
|
|
376
392
|
} catch (e) {
|
|
377
393
|
throw console.error("Resend verification failed:", e), e;
|
|
378
394
|
}
|
|
379
|
-
},
|
|
395
|
+
}, M = r(async () => {
|
|
380
396
|
y(!0);
|
|
381
397
|
try {
|
|
382
398
|
let e = [];
|
|
383
399
|
if (n) {
|
|
384
|
-
let t = await
|
|
400
|
+
let t = await L.get("/api/v1/users/me/ally-codes");
|
|
385
401
|
h(t.ally_codes), e = t.ally_codes.map((e) => e.ally_code);
|
|
386
|
-
let n =
|
|
402
|
+
let n = z();
|
|
387
403
|
n.length > 0 && x({
|
|
388
404
|
show: !0,
|
|
389
405
|
localStorageCodes: n.map((e) => e.ally_code)
|
|
390
406
|
});
|
|
391
407
|
} else {
|
|
392
|
-
let t =
|
|
408
|
+
let t = z();
|
|
393
409
|
h(t), e = t.map((e) => e.ally_code);
|
|
394
410
|
}
|
|
395
411
|
let t = me(), r = t && e.includes(t) ? t : null;
|
|
396
|
-
_(r), r !== t &&
|
|
412
|
+
_(r), r !== t && B(r);
|
|
397
413
|
} catch (e) {
|
|
398
414
|
console.error("Failed to fetch ally codes:", e), h([]);
|
|
399
415
|
} finally {
|
|
400
416
|
y(!1);
|
|
401
417
|
}
|
|
402
|
-
}, [n]),
|
|
403
|
-
n && typeof e == "number" ? (await
|
|
404
|
-
}, [n,
|
|
405
|
-
if (_(e),
|
|
418
|
+
}, [n]), N = r(async (e) => {
|
|
419
|
+
n && typeof e == "number" ? (await L.put(`/api/v1/users/me/ally-codes/${e}/use`, {}), await M()) : !n && typeof e == "string" && (pe(e), h(z()));
|
|
420
|
+
}, [n, M]), P = r((e) => {
|
|
421
|
+
if (_(e), B(e), e && n) {
|
|
406
422
|
let t = m.find((t) => "ally_code" in t && t.ally_code === e);
|
|
407
|
-
t && "id" in t &&
|
|
423
|
+
t && "id" in t && N(t.id);
|
|
408
424
|
} else e && !n && pe(e);
|
|
409
425
|
}, [
|
|
410
426
|
n,
|
|
411
427
|
m,
|
|
412
|
-
|
|
413
|
-
]),
|
|
428
|
+
N
|
|
429
|
+
]), F = r(async (e) => {
|
|
414
430
|
if (!/^\d{9}$/.test(e)) throw Error("Ally code must be exactly 9 digits");
|
|
415
431
|
if (n) {
|
|
416
|
-
let t = await
|
|
417
|
-
h((e) => [t, ...e]), m.length === 0 &&
|
|
432
|
+
let t = await L.post("/api/v1/users/me/ally-codes", { ally_code: e });
|
|
433
|
+
h((e) => [t, ...e]), m.length === 0 && P(e);
|
|
418
434
|
} else {
|
|
419
|
-
let t = await
|
|
435
|
+
let t = await L.get(`/api/v1/player-data/player/${e}`);
|
|
420
436
|
if (!t) throw Error("Invalid ally code - player not found");
|
|
421
437
|
de({
|
|
422
438
|
ally_code: e,
|
|
423
439
|
player_name: t.data?.name ?? null,
|
|
424
440
|
last_used_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
425
|
-
}), h(
|
|
441
|
+
}), h(z()), m.length === 0 && P(e);
|
|
426
442
|
}
|
|
427
443
|
}, [
|
|
428
444
|
n,
|
|
429
445
|
m.length,
|
|
430
|
-
|
|
446
|
+
P
|
|
431
447
|
]), re = r(async (e) => {
|
|
432
|
-
n && typeof e == "number" ? (await
|
|
448
|
+
n && typeof e == "number" ? (await L.delete(`/api/v1/users/me/ally-codes/${e}`), h((t) => t.filter((t) => "id" in t && t.id !== e))) : !n && typeof e == "string" && (fe(e), h(z()), g === e && P(null));
|
|
433
449
|
}, [
|
|
434
450
|
n,
|
|
435
451
|
g,
|
|
436
|
-
|
|
437
|
-
]),
|
|
452
|
+
P
|
|
453
|
+
]), I = r(() => {
|
|
438
454
|
x({
|
|
439
455
|
show: !1,
|
|
440
456
|
localStorageCodes: []
|
|
441
457
|
});
|
|
442
458
|
}, []), ie = r(async () => {
|
|
443
459
|
if (!n) return;
|
|
444
|
-
let e =
|
|
460
|
+
let e = z();
|
|
445
461
|
for (let t of e) try {
|
|
446
|
-
await
|
|
462
|
+
await F(t.ally_code);
|
|
447
463
|
} catch (e) {
|
|
448
464
|
console.error(`Failed to migrate ally code ${t.ally_code}:`, e);
|
|
449
465
|
}
|
|
450
|
-
he(),
|
|
466
|
+
he(), I();
|
|
451
467
|
}, [
|
|
452
468
|
n,
|
|
453
|
-
|
|
454
|
-
|
|
469
|
+
F,
|
|
470
|
+
I
|
|
455
471
|
]);
|
|
456
472
|
a(() => {
|
|
457
|
-
|
|
458
|
-
}, [
|
|
473
|
+
M();
|
|
474
|
+
}, [M]);
|
|
459
475
|
let ae = {
|
|
460
476
|
user: n,
|
|
461
477
|
isAuthenticated: !!n,
|
|
@@ -463,29 +479,31 @@ var _ = [
|
|
|
463
479
|
login: C,
|
|
464
480
|
register: w,
|
|
465
481
|
logout: T,
|
|
482
|
+
logoutAll: te,
|
|
466
483
|
refreshUser: ee,
|
|
467
|
-
forgotPassword:
|
|
468
|
-
resetPassword:
|
|
469
|
-
resendVerification:
|
|
484
|
+
forgotPassword: A,
|
|
485
|
+
resetPassword: j,
|
|
486
|
+
resendVerification: ne,
|
|
487
|
+
updateAccount: k,
|
|
470
488
|
authEnabled: u,
|
|
471
489
|
isLoadingFeatures: f,
|
|
472
490
|
allyCodes: m,
|
|
473
491
|
selectedAllyCode: g,
|
|
474
492
|
isLoadingAllyCodes: v,
|
|
475
|
-
fetchAllyCodes:
|
|
476
|
-
addAllyCode:
|
|
493
|
+
fetchAllyCodes: M,
|
|
494
|
+
addAllyCode: F,
|
|
477
495
|
removeAllyCode: re,
|
|
478
|
-
selectAllyCode:
|
|
479
|
-
updateAllyCodeLastUsed:
|
|
496
|
+
selectAllyCode: P,
|
|
497
|
+
updateAllyCodeLastUsed: N,
|
|
480
498
|
migrationPrompt: b,
|
|
481
|
-
dismissMigrationPrompt:
|
|
499
|
+
dismissMigrationPrompt: I,
|
|
482
500
|
migrateLocalStorageCodes: ie
|
|
483
501
|
};
|
|
484
502
|
return /* @__PURE__ */ l(ge.Provider, {
|
|
485
503
|
value: ae,
|
|
486
504
|
children: e
|
|
487
505
|
});
|
|
488
|
-
},
|
|
506
|
+
}, V = () => {
|
|
489
507
|
let e = i(ge);
|
|
490
508
|
if (e === void 0) throw Error("useAuth must be used within an AuthProvider");
|
|
491
509
|
return e;
|
|
@@ -511,7 +529,7 @@ function ve({ isOpen: e, onClose: t, triggerRef: n, panelRef: r }) {
|
|
|
511
529
|
r
|
|
512
530
|
]);
|
|
513
531
|
}
|
|
514
|
-
var
|
|
532
|
+
var H = {
|
|
515
533
|
navMenu: "_navMenu_vspnm_1",
|
|
516
534
|
trigger: "_trigger_vspnm_8",
|
|
517
535
|
tabActive: "_tabActive_vspnm_29",
|
|
@@ -525,7 +543,7 @@ var B = {
|
|
|
525
543
|
groupItems: "_groupItems_vspnm_97",
|
|
526
544
|
groupItem: "_groupItem_vspnm_97"
|
|
527
545
|
}, ye = ({ app: e, isCurrentApp: t, activeSectionId: n, isOpen: r, onOpenChange: i, onSectionClick: a }) => {
|
|
528
|
-
let { isAuthenticated: s, user: c } =
|
|
546
|
+
let { isAuthenticated: s, user: c } = V(), d = o(null), f = o(null), p = `navmenu-panel-${e.id}`;
|
|
529
547
|
ve({
|
|
530
548
|
isOpen: r,
|
|
531
549
|
onClose: () => i(!1),
|
|
@@ -542,24 +560,24 @@ var B = {
|
|
|
542
560
|
let i = t && n === e.id;
|
|
543
561
|
return /* @__PURE__ */ l("a", {
|
|
544
562
|
href: e.href,
|
|
545
|
-
className: `${
|
|
563
|
+
className: `${H.sectionLink} ${r ?? ""} ${i ? H.sectionActive : ""}`,
|
|
546
564
|
"aria-current": i ? "page" : void 0,
|
|
547
565
|
onClick: h(e),
|
|
548
566
|
children: e.label
|
|
549
567
|
}, e.id);
|
|
550
568
|
};
|
|
551
569
|
return /* @__PURE__ */ u("div", {
|
|
552
|
-
className:
|
|
570
|
+
className: H.navMenu,
|
|
553
571
|
children: [/* @__PURE__ */ u("button", {
|
|
554
572
|
type: "button",
|
|
555
573
|
ref: d,
|
|
556
|
-
className: `${
|
|
574
|
+
className: `${H.trigger} ${t ? H.tabActive : ""}`,
|
|
557
575
|
"aria-expanded": r,
|
|
558
576
|
"aria-controls": p,
|
|
559
577
|
"aria-haspopup": "true",
|
|
560
578
|
onClick: () => i(!r),
|
|
561
579
|
children: [e.label, /* @__PURE__ */ l("svg", {
|
|
562
|
-
className:
|
|
580
|
+
className: H.chevron,
|
|
563
581
|
width: "10",
|
|
564
582
|
height: "6",
|
|
565
583
|
viewBox: "0 0 10 6",
|
|
@@ -576,9 +594,9 @@ var B = {
|
|
|
576
594
|
}), r && /* @__PURE__ */ l("div", {
|
|
577
595
|
id: p,
|
|
578
596
|
ref: f,
|
|
579
|
-
className:
|
|
597
|
+
className: H.panel,
|
|
580
598
|
children: e.status === "coming-soon" ? /* @__PURE__ */ l("div", {
|
|
581
|
-
className:
|
|
599
|
+
className: H.comingSoon,
|
|
582
600
|
children: "Coming soon"
|
|
583
601
|
}) : /* @__PURE__ */ l("nav", {
|
|
584
602
|
"aria-label": `${e.label} sections`,
|
|
@@ -587,10 +605,10 @@ var B = {
|
|
|
587
605
|
if (!g(e)) return m(e) ? v(e) : null;
|
|
588
606
|
let t = e.items.filter(m);
|
|
589
607
|
return /* @__PURE__ */ u("div", {
|
|
590
|
-
className:
|
|
591
|
-
children: [v(e,
|
|
592
|
-
className:
|
|
593
|
-
children: t.map((e) => v(e,
|
|
608
|
+
className: H.group,
|
|
609
|
+
children: [v(e, H.groupLabel), /* @__PURE__ */ l("div", {
|
|
610
|
+
className: H.groupItems,
|
|
611
|
+
children: t.map((e) => v(e, H.groupItem))
|
|
594
612
|
})]
|
|
595
613
|
}, e.id);
|
|
596
614
|
})
|
|
@@ -630,7 +648,7 @@ var B = {
|
|
|
630
648
|
})
|
|
631
649
|
}));
|
|
632
650
|
xe.displayName = "NavBurger";
|
|
633
|
-
var
|
|
651
|
+
var U = {
|
|
634
652
|
selectWrapper: "_selectWrapper_ir4bq_1",
|
|
635
653
|
fullWidth: "_fullWidth_ir4bq_7",
|
|
636
654
|
label: "_label_ir4bq_11",
|
|
@@ -644,22 +662,22 @@ var V = {
|
|
|
644
662
|
}, Se = e.forwardRef(({ label: e, error: t, helperText: n, options: r, placeholder: i, fullWidth: a = !1, className: o = "", id: s, ...c }, d) => {
|
|
645
663
|
let f = s || `select-${Math.random().toString(36).substr(2, 9)}`, p = !!t;
|
|
646
664
|
return /* @__PURE__ */ u("div", {
|
|
647
|
-
className: `${
|
|
665
|
+
className: `${U.selectWrapper} ${a ? U.fullWidth : ""} ${o}`,
|
|
648
666
|
children: [
|
|
649
667
|
e && /* @__PURE__ */ u("label", {
|
|
650
668
|
htmlFor: f,
|
|
651
|
-
className:
|
|
669
|
+
className: U.label,
|
|
652
670
|
children: [e, c.required && /* @__PURE__ */ l("span", {
|
|
653
|
-
className:
|
|
671
|
+
className: U.required,
|
|
654
672
|
children: "*"
|
|
655
673
|
})]
|
|
656
674
|
}),
|
|
657
675
|
/* @__PURE__ */ u("div", {
|
|
658
|
-
className:
|
|
676
|
+
className: U.selectContainer,
|
|
659
677
|
children: [/* @__PURE__ */ u("select", {
|
|
660
678
|
ref: d,
|
|
661
679
|
id: f,
|
|
662
|
-
className: `${
|
|
680
|
+
className: `${U.select} ${p ? U.error : ""}`,
|
|
663
681
|
...c,
|
|
664
682
|
children: [
|
|
665
683
|
i && /* @__PURE__ */ l("option", {
|
|
@@ -675,23 +693,23 @@ var V = {
|
|
|
675
693
|
!r && c.children
|
|
676
694
|
]
|
|
677
695
|
}), /* @__PURE__ */ l("span", {
|
|
678
|
-
className:
|
|
696
|
+
className: U.arrow,
|
|
679
697
|
children: "▼"
|
|
680
698
|
})]
|
|
681
699
|
}),
|
|
682
700
|
t && /* @__PURE__ */ l("span", {
|
|
683
|
-
className:
|
|
701
|
+
className: U.errorText,
|
|
684
702
|
children: t
|
|
685
703
|
}),
|
|
686
704
|
n && !t && /* @__PURE__ */ l("span", {
|
|
687
|
-
className:
|
|
705
|
+
className: U.helperText,
|
|
688
706
|
children: n
|
|
689
707
|
})
|
|
690
708
|
]
|
|
691
709
|
});
|
|
692
710
|
});
|
|
693
711
|
Se.displayName = "Select";
|
|
694
|
-
var
|
|
712
|
+
var W = {
|
|
695
713
|
button: "_button_159ms_1",
|
|
696
714
|
sm: "_sm_159ms_22",
|
|
697
715
|
md: "_md_159ms_28",
|
|
@@ -707,18 +725,18 @@ var H = {
|
|
|
707
725
|
spinner: "_spinner_159ms_116",
|
|
708
726
|
spin: "_spin_159ms_116",
|
|
709
727
|
loadingText: "_loadingText_159ms_131"
|
|
710
|
-
},
|
|
711
|
-
className: `${
|
|
728
|
+
}, G = ({ children: e, variant: t = "primary", size: n = "md", fullWidth: r = !1, loading: i = !1, disabled: a = !1, className: o = "", ...s }) => /* @__PURE__ */ l("button", {
|
|
729
|
+
className: `${W.button} ${W[t]} ${W[n]} ${r ? W.fullWidth : ""} ${i ? W.loading : ""} ${o}`,
|
|
712
730
|
disabled: a || i,
|
|
713
731
|
...s,
|
|
714
732
|
children: i ? /* @__PURE__ */ u("span", {
|
|
715
|
-
className:
|
|
716
|
-
children: [/* @__PURE__ */ l("span", { className:
|
|
717
|
-
className:
|
|
733
|
+
className: W.loadingSpinner,
|
|
734
|
+
children: [/* @__PURE__ */ l("span", { className: W.spinner }), /* @__PURE__ */ l("span", {
|
|
735
|
+
className: W.loadingText,
|
|
718
736
|
children: e
|
|
719
737
|
})]
|
|
720
738
|
}) : e
|
|
721
|
-
}),
|
|
739
|
+
}), K = {
|
|
722
740
|
inputWrapper: "_inputWrapper_15t4g_1",
|
|
723
741
|
fullWidth: "_fullWidth_15t4g_7",
|
|
724
742
|
label: "_label_15t4g_11",
|
|
@@ -730,28 +748,28 @@ var H = {
|
|
|
730
748
|
}, Ce = e.forwardRef(({ label: e, error: t, helperText: n, fullWidth: r = !1, className: i = "", id: a, ...o }, s) => {
|
|
731
749
|
let c = a || `input-${Math.random().toString(36).substr(2, 9)}`, d = !!t;
|
|
732
750
|
return /* @__PURE__ */ u("div", {
|
|
733
|
-
className: `${
|
|
751
|
+
className: `${K.inputWrapper} ${r ? K.fullWidth : ""} ${i}`,
|
|
734
752
|
children: [
|
|
735
753
|
e && /* @__PURE__ */ u("label", {
|
|
736
754
|
htmlFor: c,
|
|
737
|
-
className:
|
|
755
|
+
className: K.label,
|
|
738
756
|
children: [e, o.required && /* @__PURE__ */ l("span", {
|
|
739
|
-
className:
|
|
757
|
+
className: K.required,
|
|
740
758
|
children: "*"
|
|
741
759
|
})]
|
|
742
760
|
}),
|
|
743
761
|
/* @__PURE__ */ l("input", {
|
|
744
762
|
ref: s,
|
|
745
763
|
id: c,
|
|
746
|
-
className: `${
|
|
764
|
+
className: `${K.input} ${d ? K.error : ""}`,
|
|
747
765
|
...o
|
|
748
766
|
}),
|
|
749
767
|
t && /* @__PURE__ */ l("span", {
|
|
750
|
-
className:
|
|
768
|
+
className: K.errorText,
|
|
751
769
|
children: t
|
|
752
770
|
}),
|
|
753
771
|
n && !t && /* @__PURE__ */ l("span", {
|
|
754
|
-
className:
|
|
772
|
+
className: K.helperText,
|
|
755
773
|
children: n
|
|
756
774
|
})
|
|
757
775
|
]
|
|
@@ -760,7 +778,7 @@ var H = {
|
|
|
760
778
|
Ce.displayName = "Input";
|
|
761
779
|
//#endregion
|
|
762
780
|
//#region src/utils/formatAllyCode.ts
|
|
763
|
-
var
|
|
781
|
+
var q = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e.slice(6, 9)}`, we = (e) => e.replace(/-/g, ""), J = {
|
|
764
782
|
allyCodeDropdown: "_allyCodeDropdown_1pawi_1",
|
|
765
783
|
select: "_select_1pawi_8",
|
|
766
784
|
manageButton: "_manageButton_1pawi_12",
|
|
@@ -774,7 +792,7 @@ var G = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
|
|
|
774
792
|
doneButton: "_doneButton_1pawi_88",
|
|
775
793
|
inline: "_inline_1pawi_107"
|
|
776
794
|
}, Te = ({ onAllyCodeSelected: e, className: t = "", isOpen: n, onOpenChange: r, variant: i = "floating" }) => {
|
|
777
|
-
let { allyCodes: a, selectedAllyCode: c, selectAllyCode: d, removeAllyCode: f, addAllyCode: p, isLoadingAllyCodes: m } =
|
|
795
|
+
let { allyCodes: a, selectedAllyCode: c, selectAllyCode: d, removeAllyCode: f, addAllyCode: p, isLoadingAllyCodes: m } = V(), [h, g] = s(!1), _ = n ?? h, v = (e) => {
|
|
778
796
|
g(e), r?.(e);
|
|
779
797
|
}, [y, b] = s(""), [x, S] = s(""), [C, w] = s(""), [T, E] = s(!1), D = o(null), O = o(null);
|
|
780
798
|
ve({
|
|
@@ -785,14 +803,17 @@ var G = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
|
|
|
785
803
|
});
|
|
786
804
|
let ee = a.map((e) => ({
|
|
787
805
|
value: e.ally_code,
|
|
788
|
-
label: e.player_name ? `${e.player_name} (${
|
|
789
|
-
})),
|
|
806
|
+
label: e.player_name ? `${e.player_name} (${q(e.ally_code)})` : q(e.ally_code)
|
|
807
|
+
})), te = (t) => {
|
|
790
808
|
let n = t.target.value || null;
|
|
791
809
|
d(n), e?.(n);
|
|
792
|
-
},
|
|
810
|
+
}, k = async (e) => {
|
|
793
811
|
let t = a.find((t) => t.ally_code === e);
|
|
794
|
-
|
|
795
|
-
|
|
812
|
+
if (t) {
|
|
813
|
+
let e = "id" in t ? t.id : t.ally_code;
|
|
814
|
+
await f(e);
|
|
815
|
+
}
|
|
816
|
+
}, A = async () => {
|
|
796
817
|
if (S(""), w(""), !/^\d{9}$/.test(y)) {
|
|
797
818
|
S("Ally code must be exactly 9 digits");
|
|
798
819
|
return;
|
|
@@ -807,80 +828,80 @@ var G = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
|
|
|
807
828
|
}
|
|
808
829
|
}, j = a.length > 0;
|
|
809
830
|
return /* @__PURE__ */ u("div", {
|
|
810
|
-
className: `${
|
|
831
|
+
className: `${J.allyCodeDropdown} ${i === "inline" ? J.inline : ""} ${t}`,
|
|
811
832
|
children: [
|
|
812
833
|
j && /* @__PURE__ */ l(Se, {
|
|
813
834
|
options: ee,
|
|
814
835
|
value: c || "",
|
|
815
|
-
onChange:
|
|
836
|
+
onChange: te,
|
|
816
837
|
placeholder: "Select ally code",
|
|
817
838
|
disabled: m,
|
|
818
|
-
className:
|
|
839
|
+
className: J.select
|
|
819
840
|
}),
|
|
820
841
|
_ && /* @__PURE__ */ u("div", {
|
|
821
|
-
className:
|
|
842
|
+
className: J.managePanel,
|
|
822
843
|
ref: O,
|
|
823
844
|
id: "ally-code-manage-panel",
|
|
824
845
|
children: [
|
|
825
846
|
/* @__PURE__ */ l("h4", { children: "Manage Ally Codes" }),
|
|
826
847
|
/* @__PURE__ */ u("div", {
|
|
827
|
-
className:
|
|
848
|
+
className: J.addSection,
|
|
828
849
|
children: [
|
|
829
850
|
/* @__PURE__ */ u("div", {
|
|
830
|
-
className:
|
|
851
|
+
className: J.addInputGroup,
|
|
831
852
|
children: [/* @__PURE__ */ l(Ce, {
|
|
832
853
|
type: "text",
|
|
833
854
|
placeholder: "9-digit ally code",
|
|
834
855
|
value: y,
|
|
835
856
|
onChange: (e) => b(e.target.value.replace(/\D/g, "").slice(0, 9)),
|
|
836
857
|
disabled: T
|
|
837
|
-
}), /* @__PURE__ */ l(
|
|
858
|
+
}), /* @__PURE__ */ l(G, {
|
|
838
859
|
variant: "primary",
|
|
839
860
|
size: "sm",
|
|
840
|
-
onClick:
|
|
861
|
+
onClick: A,
|
|
841
862
|
loading: T,
|
|
842
863
|
disabled: y.length !== 9,
|
|
843
864
|
children: "Add"
|
|
844
865
|
})]
|
|
845
866
|
}),
|
|
846
867
|
x && /* @__PURE__ */ l("div", {
|
|
847
|
-
className:
|
|
868
|
+
className: J.error,
|
|
848
869
|
children: x
|
|
849
870
|
}),
|
|
850
871
|
C && /* @__PURE__ */ l("div", {
|
|
851
|
-
className:
|
|
872
|
+
className: J.success,
|
|
852
873
|
children: C
|
|
853
874
|
})
|
|
854
875
|
]
|
|
855
876
|
}),
|
|
856
877
|
/* @__PURE__ */ l("div", {
|
|
857
|
-
className:
|
|
878
|
+
className: J.codesList,
|
|
858
879
|
children: a.map((e) => /* @__PURE__ */ u("div", {
|
|
859
|
-
className:
|
|
860
|
-
children: [/* @__PURE__ */ l("span", { children: e.player_name ? `${e.player_name} (${
|
|
880
|
+
className: J.codeItem,
|
|
881
|
+
children: [/* @__PURE__ */ l("span", { children: e.player_name ? `${e.player_name} (${q(e.ally_code)})` : q(e.ally_code) }), /* @__PURE__ */ l(G, {
|
|
861
882
|
variant: "ghost",
|
|
862
883
|
size: "sm",
|
|
863
|
-
onClick: () =>
|
|
884
|
+
onClick: () => k(e.ally_code),
|
|
864
885
|
children: "Remove"
|
|
865
886
|
})]
|
|
866
887
|
}, e.ally_code))
|
|
867
888
|
}),
|
|
868
|
-
/* @__PURE__ */ l(
|
|
889
|
+
/* @__PURE__ */ l(G, {
|
|
869
890
|
variant: "secondary",
|
|
870
891
|
size: "sm",
|
|
871
892
|
onClick: () => v(!1),
|
|
872
|
-
className:
|
|
893
|
+
className: J.doneButton,
|
|
873
894
|
children: "Done"
|
|
874
895
|
})
|
|
875
896
|
]
|
|
876
897
|
}),
|
|
877
898
|
/* @__PURE__ */ l("span", {
|
|
878
899
|
ref: D,
|
|
879
|
-
children: /* @__PURE__ */ l(
|
|
900
|
+
children: /* @__PURE__ */ l(G, {
|
|
880
901
|
variant: "ghost",
|
|
881
902
|
size: "sm",
|
|
882
903
|
onClick: () => v(!_),
|
|
883
|
-
className:
|
|
904
|
+
className: J.manageButton,
|
|
884
905
|
"aria-expanded": _,
|
|
885
906
|
"aria-controls": "ally-code-manage-panel",
|
|
886
907
|
"aria-haspopup": "true",
|
|
@@ -889,26 +910,26 @@ var G = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
|
|
|
889
910
|
})
|
|
890
911
|
]
|
|
891
912
|
});
|
|
892
|
-
},
|
|
913
|
+
}, Ee = {
|
|
893
914
|
authCluster: "_authCluster_17o10_1",
|
|
894
915
|
userLink: "_userLink_17o10_7",
|
|
895
916
|
adminLink: "_adminLink_17o10_16"
|
|
896
|
-
},
|
|
897
|
-
let { user: t, isAuthenticated: n, logout: r, authEnabled: i } =
|
|
917
|
+
}, De = ({ showAuth: e = !0 }) => {
|
|
918
|
+
let { user: t, isAuthenticated: n, logout: r, authEnabled: i } = V();
|
|
898
919
|
return e ? n ? /* @__PURE__ */ u("div", {
|
|
899
|
-
className:
|
|
920
|
+
className: Ee.authCluster,
|
|
900
921
|
children: [
|
|
901
922
|
t?.role === "admin" && /* @__PURE__ */ l("a", {
|
|
902
923
|
href: "/admin/users",
|
|
903
|
-
className:
|
|
924
|
+
className: Ee.adminLink,
|
|
904
925
|
children: "Admin"
|
|
905
926
|
}),
|
|
906
927
|
/* @__PURE__ */ l("a", {
|
|
907
928
|
href: "/profile",
|
|
908
|
-
className:
|
|
929
|
+
className: Ee.userLink,
|
|
909
930
|
children: t?.username
|
|
910
931
|
}),
|
|
911
|
-
/* @__PURE__ */ l(
|
|
932
|
+
/* @__PURE__ */ l(G, {
|
|
912
933
|
variant: "ghost",
|
|
913
934
|
size: "sm",
|
|
914
935
|
onClick: () => {
|
|
@@ -918,24 +939,24 @@ var G = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
|
|
|
918
939
|
})
|
|
919
940
|
]
|
|
920
941
|
}) : i ? /* @__PURE__ */ u("div", {
|
|
921
|
-
className:
|
|
942
|
+
className: Ee.authCluster,
|
|
922
943
|
children: [/* @__PURE__ */ l("a", {
|
|
923
944
|
href: "/login",
|
|
924
|
-
children: /* @__PURE__ */ l(
|
|
945
|
+
children: /* @__PURE__ */ l(G, {
|
|
925
946
|
variant: "ghost",
|
|
926
947
|
size: "sm",
|
|
927
948
|
children: "Login"
|
|
928
949
|
})
|
|
929
950
|
}), /* @__PURE__ */ l("a", {
|
|
930
951
|
href: "/register",
|
|
931
|
-
children: /* @__PURE__ */ l(
|
|
952
|
+
children: /* @__PURE__ */ l(G, {
|
|
932
953
|
variant: "primary",
|
|
933
954
|
size: "sm",
|
|
934
955
|
children: "Sign Up"
|
|
935
956
|
})
|
|
936
957
|
})]
|
|
937
958
|
}) : null : null;
|
|
938
|
-
},
|
|
959
|
+
}, Y = {
|
|
939
960
|
backdrop: "_backdrop_3ax21_1",
|
|
940
961
|
panel: "_panel_3ax21_11",
|
|
941
962
|
accordion: "_accordion_3ax21_24",
|
|
@@ -955,14 +976,23 @@ var G = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
|
|
|
955
976
|
allySection: "_allySection_3ax21_112",
|
|
956
977
|
extrasSection: "_extrasSection_3ax21_113",
|
|
957
978
|
accountSection: "_accountSection_3ax21_114"
|
|
958
|
-
},
|
|
959
|
-
let { isAuthenticated: h, user: v } =
|
|
979
|
+
}, Oe = "a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])", ke = ({ isOpen: e, onClose: t, currentApp: n, activeSectionId: r, onSectionClick: i, rightExtras: c, showAuth: f, panelId: p, returnFocusRef: m }) => {
|
|
980
|
+
let { isAuthenticated: h, user: v } = V(), [y, b] = s(n === "hub" ? null : n), x = o(null);
|
|
960
981
|
if (a(() => (e ? document.body.style.overflow = "hidden" : document.body.style.overflow = "unset", () => {
|
|
961
982
|
document.body.style.overflow = "unset";
|
|
962
983
|
}), [e]), a(() => {
|
|
963
984
|
if (!e) return;
|
|
964
985
|
let r = (e) => {
|
|
965
|
-
e.key === "Escape"
|
|
986
|
+
if (e.key === "Escape") {
|
|
987
|
+
t(), m.current?.focus();
|
|
988
|
+
return;
|
|
989
|
+
}
|
|
990
|
+
if (e.key === "Tab") {
|
|
991
|
+
let t = x.current?.querySelectorAll(Oe);
|
|
992
|
+
if (!t || t.length === 0) return;
|
|
993
|
+
let n = t[0], r = t[t.length - 1], i = document.activeElement, a = i === x.current || !x.current?.contains(i);
|
|
994
|
+
e.shiftKey && (i === n || a) ? (e.preventDefault(), r.focus()) : !e.shiftKey && (i === r || a) && (e.preventDefault(), n.focus());
|
|
995
|
+
}
|
|
966
996
|
};
|
|
967
997
|
return document.addEventListener("keydown", r), b(n === "hub" ? null : n), x.current?.focus(), () => document.removeEventListener("keydown", r);
|
|
968
998
|
}, [e]), !e) return null;
|
|
@@ -970,7 +1000,7 @@ var G = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
|
|
|
970
1000
|
e === n && i?.(r, a), t();
|
|
971
1001
|
};
|
|
972
1002
|
return d(/* @__PURE__ */ l("div", {
|
|
973
|
-
className:
|
|
1003
|
+
className: Y.backdrop,
|
|
974
1004
|
onClick: t,
|
|
975
1005
|
children: /* @__PURE__ */ u("div", {
|
|
976
1006
|
ref: x,
|
|
@@ -979,32 +1009,32 @@ var G = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
|
|
|
979
1009
|
"aria-modal": "true",
|
|
980
1010
|
"aria-label": "Navigation menu",
|
|
981
1011
|
tabIndex: -1,
|
|
982
|
-
className:
|
|
1012
|
+
className: Y.panel,
|
|
983
1013
|
onClick: (e) => e.stopPropagation(),
|
|
984
1014
|
children: [
|
|
985
1015
|
/* @__PURE__ */ l("div", {
|
|
986
|
-
className:
|
|
1016
|
+
className: Y.accordion,
|
|
987
1017
|
children: _.map((e) => {
|
|
988
1018
|
let t = y === e.id, i = n === e.id, a = (e) => !(e.requiresAuth && !h || e.roles && (!v || !e.roles.includes(v.role))), o = `mobile-accordion-${e.id}`, s = (t, n) => {
|
|
989
1019
|
let a = i && r === t.id;
|
|
990
1020
|
return /* @__PURE__ */ l("a", {
|
|
991
1021
|
href: t.href,
|
|
992
|
-
className: `${
|
|
1022
|
+
className: `${Y.sectionLink} ${n ?? ""} ${a ? Y.sectionActive : ""}`,
|
|
993
1023
|
"aria-current": a ? "page" : void 0,
|
|
994
1024
|
onClick: S(e.id, t),
|
|
995
1025
|
children: t.label
|
|
996
1026
|
}, t.id);
|
|
997
1027
|
};
|
|
998
1028
|
return /* @__PURE__ */ u("div", {
|
|
999
|
-
className:
|
|
1029
|
+
className: Y.accordionItem,
|
|
1000
1030
|
children: [/* @__PURE__ */ u("button", {
|
|
1001
1031
|
type: "button",
|
|
1002
|
-
className: `${
|
|
1032
|
+
className: `${Y.accordionHeader} ${i ? Y.currentApp : ""}`,
|
|
1003
1033
|
"aria-expanded": t,
|
|
1004
1034
|
"aria-controls": o,
|
|
1005
1035
|
onClick: () => b(t ? null : e.id),
|
|
1006
1036
|
children: [e.label, /* @__PURE__ */ l("svg", {
|
|
1007
|
-
className: `${
|
|
1037
|
+
className: `${Y.chevron} ${t ? Y.chevronOpen : ""}`,
|
|
1008
1038
|
width: "10",
|
|
1009
1039
|
height: "6",
|
|
1010
1040
|
viewBox: "0 0 10 6",
|
|
@@ -1020,18 +1050,18 @@ var G = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
|
|
|
1020
1050
|
})]
|
|
1021
1051
|
}), t && /* @__PURE__ */ l("div", {
|
|
1022
1052
|
id: o,
|
|
1023
|
-
className:
|
|
1053
|
+
className: Y.accordionPanel,
|
|
1024
1054
|
children: e.status === "coming-soon" ? /* @__PURE__ */ l("div", {
|
|
1025
|
-
className:
|
|
1055
|
+
className: Y.comingSoon,
|
|
1026
1056
|
children: "Coming soon"
|
|
1027
1057
|
}) : e.sections.map((e) => {
|
|
1028
1058
|
if (!g(e)) return a(e) ? s(e) : null;
|
|
1029
1059
|
let t = e.items.filter(a);
|
|
1030
1060
|
return /* @__PURE__ */ u("div", {
|
|
1031
|
-
className:
|
|
1032
|
-
children: [s(e,
|
|
1033
|
-
className:
|
|
1034
|
-
children: t.map((e) => s(e,
|
|
1061
|
+
className: Y.group,
|
|
1062
|
+
children: [s(e, Y.groupLabel), /* @__PURE__ */ l("div", {
|
|
1063
|
+
className: Y.groupItems,
|
|
1064
|
+
children: t.map((e) => s(e, Y.groupItem))
|
|
1035
1065
|
})]
|
|
1036
1066
|
}, e.id);
|
|
1037
1067
|
})
|
|
@@ -1040,26 +1070,26 @@ var G = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
|
|
|
1040
1070
|
})
|
|
1041
1071
|
}),
|
|
1042
1072
|
/* @__PURE__ */ l("div", {
|
|
1043
|
-
className:
|
|
1073
|
+
className: Y.allySection,
|
|
1044
1074
|
children: /* @__PURE__ */ l(Te, { variant: "inline" })
|
|
1045
1075
|
}),
|
|
1046
1076
|
c && /* @__PURE__ */ l("div", {
|
|
1047
|
-
className:
|
|
1077
|
+
className: Y.extrasSection,
|
|
1048
1078
|
children: c
|
|
1049
1079
|
}),
|
|
1050
1080
|
/* @__PURE__ */ l("div", {
|
|
1051
|
-
className:
|
|
1052
|
-
children: /* @__PURE__ */ l(
|
|
1081
|
+
className: Y.accountSection,
|
|
1082
|
+
children: /* @__PURE__ */ l(De, { showAuth: f })
|
|
1053
1083
|
})
|
|
1054
1084
|
]
|
|
1055
1085
|
})
|
|
1056
1086
|
}), document.body);
|
|
1057
|
-
},
|
|
1087
|
+
}, Ae = {
|
|
1058
1088
|
logoLink: "_logoLink_12f5f_3",
|
|
1059
1089
|
appMenus: "_appMenus_12f5f_10",
|
|
1060
1090
|
desktopRight: "_desktopRight_12f5f_19",
|
|
1061
1091
|
extrasGroup: "_extrasGroup_12f5f_25"
|
|
1062
|
-
},
|
|
1092
|
+
}, je = ({ currentApp: e, activeSectionId: t, onNavigate: n, rightExtras: r, showAuth: i = !0, className: d }) => {
|
|
1063
1093
|
let [f, p] = s(null), [m, g] = s(!1), v = o(null), y = "suite-mobile-nav-panel";
|
|
1064
1094
|
return a(() => {
|
|
1065
1095
|
let e = window.matchMedia("(max-width: 768px)"), t = () => {
|
|
@@ -1070,11 +1100,11 @@ var G = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
|
|
|
1070
1100
|
className: d,
|
|
1071
1101
|
logo: /* @__PURE__ */ l("a", {
|
|
1072
1102
|
href: "/",
|
|
1073
|
-
className:
|
|
1103
|
+
className: Ae.logoLink,
|
|
1074
1104
|
children: "The Astrogator's Table"
|
|
1075
1105
|
}),
|
|
1076
1106
|
leftContent: /* @__PURE__ */ l("nav", {
|
|
1077
|
-
className:
|
|
1107
|
+
className: Ae.appMenus,
|
|
1078
1108
|
children: _.map((r) => /* @__PURE__ */ l(ye, {
|
|
1079
1109
|
app: r,
|
|
1080
1110
|
isCurrentApp: e === r.id,
|
|
@@ -1085,17 +1115,17 @@ var G = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
|
|
|
1085
1115
|
}, r.id))
|
|
1086
1116
|
}),
|
|
1087
1117
|
rightContent: /* @__PURE__ */ u(c, { children: [/* @__PURE__ */ u("div", {
|
|
1088
|
-
className:
|
|
1118
|
+
className: Ae.desktopRight,
|
|
1089
1119
|
children: [
|
|
1090
1120
|
r && /* @__PURE__ */ l("div", {
|
|
1091
|
-
className:
|
|
1121
|
+
className: Ae.extrasGroup,
|
|
1092
1122
|
children: r
|
|
1093
1123
|
}),
|
|
1094
1124
|
/* @__PURE__ */ l(Te, {
|
|
1095
1125
|
isOpen: f === "ally",
|
|
1096
1126
|
onOpenChange: (e) => p(e ? "ally" : null)
|
|
1097
1127
|
}),
|
|
1098
|
-
/* @__PURE__ */ l(
|
|
1128
|
+
/* @__PURE__ */ l(De, { showAuth: i })
|
|
1099
1129
|
]
|
|
1100
1130
|
}), /* @__PURE__ */ l(xe, {
|
|
1101
1131
|
ref: v,
|
|
@@ -1105,7 +1135,7 @@ var G = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
|
|
|
1105
1135
|
},
|
|
1106
1136
|
controlsId: y
|
|
1107
1137
|
})] })
|
|
1108
|
-
}), /* @__PURE__ */ l(
|
|
1138
|
+
}), /* @__PURE__ */ l(ke, {
|
|
1109
1139
|
isOpen: m,
|
|
1110
1140
|
onClose: () => g(!1),
|
|
1111
1141
|
currentApp: e,
|
|
@@ -1122,7 +1152,7 @@ var G = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
|
|
|
1122
1152
|
defaultContent: "_defaultContent_zjuj8_13",
|
|
1123
1153
|
copyright: "_copyright_zjuj8_21",
|
|
1124
1154
|
disclaimer: "_disclaimer_zjuj8_26"
|
|
1125
|
-
},
|
|
1155
|
+
}, Me = ({ children: e, className: t = "" }) => /* @__PURE__ */ l("footer", {
|
|
1126
1156
|
className: `${X.footer} ${t}`,
|
|
1127
1157
|
children: /* @__PURE__ */ l("div", {
|
|
1128
1158
|
className: X.content,
|
|
@@ -1144,11 +1174,11 @@ var G = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e
|
|
|
1144
1174
|
});
|
|
1145
1175
|
//#endregion
|
|
1146
1176
|
//#region src/utils/formatTime.ts
|
|
1147
|
-
function
|
|
1177
|
+
function Ne(e) {
|
|
1148
1178
|
let t = /([zZ]|[+-]\d{2}:?\d{2})$/.test(e);
|
|
1149
1179
|
return new Date(t ? e : `${e}Z`);
|
|
1150
1180
|
}
|
|
1151
|
-
function
|
|
1181
|
+
function Pe(e, t) {
|
|
1152
1182
|
let n = Math.max(0, Math.floor((t - e.getTime()) / 1e3));
|
|
1153
1183
|
if (n < 60) return `${n}s ago`;
|
|
1154
1184
|
let r = Math.floor(n / 60);
|
|
@@ -1156,38 +1186,38 @@ function je(e, t) {
|
|
|
1156
1186
|
let i = Math.floor(r / 60);
|
|
1157
1187
|
return i < 24 ? `${i}h ago` : `${Math.floor(i / 24)}d ago`;
|
|
1158
1188
|
}
|
|
1159
|
-
function
|
|
1189
|
+
function Fe(e) {
|
|
1160
1190
|
return `${Math.floor(e / 60)}:${(e % 60).toString().padStart(2, "0")}`;
|
|
1161
1191
|
}
|
|
1162
|
-
var
|
|
1192
|
+
var Ie = {
|
|
1163
1193
|
rosterRefresh: "_rosterRefresh_1rbul_3",
|
|
1164
1194
|
updatedLabel: "_updatedLabel_1rbul_11",
|
|
1165
1195
|
refreshButton: "_refreshButton_1rbul_19",
|
|
1166
1196
|
spin: "_spin_1rbul_31"
|
|
1167
|
-
},
|
|
1197
|
+
}, Le = ({ onRefresh: e, isRefreshing: t, cachedAt: n = null, refreshAvailableAt: r = null, labelPrefix: i = "Updated", className: o = "" }) => {
|
|
1168
1198
|
let [c, d] = s(() => Date.now()), f = !!n || r != null && r > c;
|
|
1169
1199
|
a(() => {
|
|
1170
1200
|
if (!f) return;
|
|
1171
1201
|
let e = setInterval(() => d(Date.now()), 1e3);
|
|
1172
1202
|
return () => clearInterval(e);
|
|
1173
1203
|
}, [f]);
|
|
1174
|
-
let p = r ? Math.max(0, Math.ceil((r - c) / 1e3)) : 0, m = n ?
|
|
1204
|
+
let p = r ? Math.max(0, Math.ceil((r - c) / 1e3)) : 0, m = n ? Pe(Ne(n), c) : null, h = t || p > 0, g = p > 0 ? `Fresh data available in ${Fe(p)}` : "Refresh roster";
|
|
1175
1205
|
return /* @__PURE__ */ u("div", {
|
|
1176
|
-
className: `${
|
|
1206
|
+
className: `${Ie.rosterRefresh} ${o}`,
|
|
1177
1207
|
children: [m && /* @__PURE__ */ l("span", {
|
|
1178
|
-
className:
|
|
1208
|
+
className: Ie.updatedLabel,
|
|
1179
1209
|
title: g,
|
|
1180
|
-
children: p > 0 ? `${i} ${m} · fresh in ${
|
|
1181
|
-
}), /* @__PURE__ */ l(
|
|
1210
|
+
children: p > 0 ? `${i} ${m} · fresh in ${Fe(p)}` : `${i} ${m}`
|
|
1211
|
+
}), /* @__PURE__ */ l(G, {
|
|
1182
1212
|
variant: "outline",
|
|
1183
1213
|
size: "sm",
|
|
1184
1214
|
onClick: e,
|
|
1185
1215
|
disabled: h,
|
|
1186
1216
|
title: g,
|
|
1187
1217
|
"aria-label": "Refresh roster",
|
|
1188
|
-
className:
|
|
1218
|
+
className: Ie.refreshButton,
|
|
1189
1219
|
children: /* @__PURE__ */ l("span", {
|
|
1190
|
-
className: t ?
|
|
1220
|
+
className: t ? Ie.spin : void 0,
|
|
1191
1221
|
children: "⟳"
|
|
1192
1222
|
})
|
|
1193
1223
|
})]
|
|
@@ -1203,7 +1233,7 @@ var Ne = {
|
|
|
1203
1233
|
"padding-md": "_padding-md_1vw8g_43",
|
|
1204
1234
|
"padding-lg": "_padding-lg_1vw8g_47",
|
|
1205
1235
|
hoverable: "_hoverable_1vw8g_52"
|
|
1206
|
-
},
|
|
1236
|
+
}, Re = ({ children: e, variant: t = "default", chamfered: n = !1, chamferSize: r = "md", padding: i = "md", hoverable: a = !1, showDiagonalBorders: o = !0, edgeColor: s, className: d = "", onClick: f, style: p }) => {
|
|
1207
1237
|
let m = n ? r === "asymmetric" ? "chamfered-box-asymmetric" : r === "sm" ? "chamfered-box-sm" : r === "lg" ? "chamfered-box-lg" : "chamfered-box" : "", h = s ?? (n ? "var(--color-border)" : void 0), g = h ? { color: h } : void 0, _ = h ? {
|
|
1208
1238
|
...p,
|
|
1209
1239
|
"--card-edge-color": h
|
|
@@ -1233,7 +1263,7 @@ var Ne = {
|
|
|
1233
1263
|
})
|
|
1234
1264
|
] }), e]
|
|
1235
1265
|
});
|
|
1236
|
-
},
|
|
1266
|
+
}, ze = {
|
|
1237
1267
|
badge: "_badge_rk7t5_1",
|
|
1238
1268
|
sm: "_sm_rk7t5_11",
|
|
1239
1269
|
md: "_md_rk7t5_16",
|
|
@@ -1245,8 +1275,8 @@ var Ne = {
|
|
|
1245
1275
|
warning: "_warning_rk7t5_47",
|
|
1246
1276
|
error: "_error_rk7t5_52",
|
|
1247
1277
|
info: "_info_rk7t5_57"
|
|
1248
|
-
},
|
|
1249
|
-
className: `${
|
|
1278
|
+
}, Be = ({ children: e, variant: t = "default", size: n = "md", className: r = "" }) => /* @__PURE__ */ l("span", {
|
|
1279
|
+
className: `${ze.badge} ${ze[t]} ${ze[n]} ${r}`,
|
|
1250
1280
|
children: e
|
|
1251
1281
|
}), Q = {
|
|
1252
1282
|
overlay: "_overlay_1b3yt_1",
|
|
@@ -1261,7 +1291,7 @@ var Ne = {
|
|
|
1261
1291
|
title: "_title_1b3yt_53",
|
|
1262
1292
|
closeButton: "_closeButton_1b3yt_60",
|
|
1263
1293
|
content: "_content_1b3yt_78"
|
|
1264
|
-
},
|
|
1294
|
+
}, Ve = ({ isOpen: e, onClose: t, title: n, children: r, size: i = "md", closeOnOverlayClick: o = !0, className: s = "" }) => (a(() => (e ? document.body.style.overflow = "hidden" : document.body.style.overflow = "unset", () => {
|
|
1265
1295
|
document.body.style.overflow = "unset";
|
|
1266
1296
|
}), [e]), a(() => {
|
|
1267
1297
|
let n = (n) => {
|
|
@@ -1303,7 +1333,7 @@ var Ne = {
|
|
|
1303
1333
|
dot: "_dot_1uhnh_34",
|
|
1304
1334
|
bounce: "_bounce_1uhnh_1",
|
|
1305
1335
|
visuallyHidden: "_visuallyHidden_1uhnh_91"
|
|
1306
|
-
},
|
|
1336
|
+
}, He = ({ size: e = "md", variant: t = "spinner", className: n = "" }) => t === "dots" ? /* @__PURE__ */ u("div", {
|
|
1307
1337
|
className: `${$.dots} ${$[e]} ${n}`,
|
|
1308
1338
|
children: [
|
|
1309
1339
|
/* @__PURE__ */ l("span", { className: $.dot }),
|
|
@@ -1317,10 +1347,10 @@ var Ne = {
|
|
|
1317
1347
|
className: $.visuallyHidden,
|
|
1318
1348
|
children: "Loading..."
|
|
1319
1349
|
})
|
|
1320
|
-
}),
|
|
1350
|
+
}), Ue = async (e) => {
|
|
1321
1351
|
if (e.length === 0) return {};
|
|
1322
|
-
let t = [...new Set(e)], n = await
|
|
1352
|
+
let t = [...new Set(e)], n = await L.get(`/api/v1/users/lookup?ids=${t.join(",")}`);
|
|
1323
1353
|
return Object.fromEntries(n.users.map((e) => [e.id, e.username]));
|
|
1324
1354
|
};
|
|
1325
1355
|
//#endregion
|
|
1326
|
-
export { Te as AllyCodeDropdown,
|
|
1356
|
+
export { Te as AllyCodeDropdown, oe as ApiClient, _e as AuthProvider, Be as Badge, G as Button, Re as Card, p as Container, Me as Footer, Ce as Input, He as Loader, Ve as Modal, je as NavBar, Le as RosterRefresh, _ as SUITE_NAV, Se as Select, h as TopBar, L as apiClient, ae as authedFetch, he as clearAllyCodes, D as clearTokens, A as configureAuthRefresh, Ue as fetchUsernames, q as formatAllyCode, Fe as formatCountdown, Pe as formatRelativeTime, b as getAccessToken, z as getAllyCodesFromStorage, C as getRefreshToken, me as getSelectedAllyCode, se as initializeApiClient, O as isAuthenticated, g as isSuiteNavGroup, Ne as parseBackendTimestamp, j as refreshAccessToken, S as removeAccessToken, fe as removeAllyCodeFromStorage, T as removeRefreshToken, de as saveAllyCodeToStorage, x as setAccessToken, w as setRefreshToken, B as setSelectedAllyCode, E as setTokens, we as unformatAllyCode, pe as updateAllyCodeLastUsed, V as useAuth };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
|
-
import { User, LoginRequest, RegisterRequest, ForgotPasswordRequest, ResetPasswordRequest, ResendVerificationRequest, AllyCode, AllyCodeMigrationPrompt } from '../types';
|
|
2
|
+
import { User, LoginRequest, RegisterRequest, ForgotPasswordRequest, ResetPasswordRequest, ResendVerificationRequest, AllyCode, AllyCodeMigrationPrompt, UpdateAccountRequest, UpdateAccountResponse } from '../types';
|
|
3
3
|
import { StoredAllyCode } from '../services/allyCodeStorage';
|
|
4
4
|
export interface AuthContextValue {
|
|
5
5
|
user: User | null;
|
|
@@ -8,10 +8,25 @@ export interface AuthContextValue {
|
|
|
8
8
|
login: (credentials: LoginRequest) => Promise<void>;
|
|
9
9
|
register: (data: RegisterRequest) => Promise<void>;
|
|
10
10
|
logout: () => void;
|
|
11
|
+
/**
|
|
12
|
+
* Revoke every token for the account (server-side), then perform the same
|
|
13
|
+
* local sign-out as `logout()`. The local half always runs, even if the
|
|
14
|
+
* server call fails after the request lands, so the UI never stays "signed
|
|
15
|
+
* in" against a session the server will 401 on its next real call anyway.
|
|
16
|
+
*/
|
|
17
|
+
logoutAll: () => Promise<void>;
|
|
11
18
|
refreshUser: () => Promise<void>;
|
|
12
19
|
forgotPassword: (data: ForgotPasswordRequest) => Promise<string>;
|
|
13
20
|
resetPassword: (data: ResetPasswordRequest) => Promise<string>;
|
|
14
21
|
resendVerification: (data: ResendVerificationRequest) => Promise<string>;
|
|
22
|
+
/**
|
|
23
|
+
* Change email and/or password (current_password required by the backend
|
|
24
|
+
* for either). Adopts the fresh tokens the change returns and updates
|
|
25
|
+
* `user` in place — including `is_verified` flipping back to false when the
|
|
26
|
+
* email changed. Throws on a wrong/missing current_password (400) or a
|
|
27
|
+
* locked account (403), same as every other auth action here.
|
|
28
|
+
*/
|
|
29
|
+
updateAccount: (data: UpdateAccountRequest) => Promise<UpdateAccountResponse>;
|
|
15
30
|
authEnabled: boolean;
|
|
16
31
|
isLoadingFeatures: boolean;
|
|
17
32
|
allyCodes: AllyCode[] | StoredAllyCode[];
|
package/dist/src/index.d.ts
CHANGED
|
@@ -20,4 +20,4 @@ export { fetchUsernames } from './services/users';
|
|
|
20
20
|
export type { StoredAllyCode } from './services/allyCodeStorage';
|
|
21
21
|
export { formatAllyCode, unformatAllyCode } from './utils/formatAllyCode';
|
|
22
22
|
export { parseBackendTimestamp, formatRelativeTime, formatCountdown } from './utils/formatTime';
|
|
23
|
-
export type { User, LoginRequest, LoginResponse, RegisterRequest, RegisterResponse, RefreshTokenRequest, RefreshTokenResponse, ForgotPasswordRequest, ForgotPasswordResponse, ResetPasswordRequest, ResetPasswordResponse, VerifyEmailRequest, VerifyEmailResponse, ResendVerificationRequest, ResendVerificationResponse, AllyCode, AllyCodeCreate, AllyCodeListResponse, AllyCodeMigrationPrompt, ApiResponse, ApiError, PaginatedResponse, ModStat, ParsedMod, ModListResponse, EvaluationScores, ModEvaluation, EvaluationRequest, EvaluationResponse, } from './types';
|
|
23
|
+
export type { User, LoginRequest, LoginResponse, RegisterRequest, RegisterResponse, RefreshTokenRequest, RefreshTokenResponse, ForgotPasswordRequest, ForgotPasswordResponse, ResetPasswordRequest, ResetPasswordResponse, VerifyEmailRequest, VerifyEmailResponse, ResendVerificationRequest, ResendVerificationResponse, AllyCode, AllyCodeCreate, AllyCodeListResponse, AllyCodeMigrationPrompt, TokenResponse, UpdateAccountRequest, UpdateAccountResponse, LogoutAllResponse, ApiResponse, ApiError, PaginatedResponse, ModStat, ParsedMod, ModListResponse, EvaluationScores, ModEvaluation, EvaluationRequest, EvaluationResponse, } from './types';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { UpdateAccountRequest, UpdateAccountResponse } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* PATCH /users/me: change email and/or password. The backend requires
|
|
4
|
+
* `current_password` whenever either is set (a stolen access token alone must
|
|
5
|
+
* not be enough), and applies both together or not at all.
|
|
6
|
+
*
|
|
7
|
+
* A successful change revokes every outstanding token for the account,
|
|
8
|
+
* including the caller's own — so a fresh pair comes back in `tokens` and is
|
|
9
|
+
* adopted here immediately, before this function returns, so the caller's own
|
|
10
|
+
* session survives the change. `tokens` is `null` for a no-op body (nothing
|
|
11
|
+
* to change): nothing to adopt, nothing revoked.
|
|
12
|
+
*/
|
|
13
|
+
export declare const updateAccount: (data: UpdateAccountRequest) => Promise<UpdateAccountResponse>;
|
|
14
|
+
/**
|
|
15
|
+
* POST /auth/logout-all: revoke every token for the account, including the
|
|
16
|
+
* caller's own. This only reaches the server — it does NOT clear this
|
|
17
|
+
* browser's stored tokens; the caller (AuthContext's `logoutAll`) does the
|
|
18
|
+
* local half so "revoked server-side" and "signed out here" always happen
|
|
19
|
+
* together.
|
|
20
|
+
*/
|
|
21
|
+
export declare const logoutAllSessions: () => Promise<string>;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export type { User, LoginRequest, LoginResponse, RegisterRequest, RegisterResponse, RefreshTokenRequest, RefreshTokenResponse, ForgotPasswordRequest, ForgotPasswordResponse, ResetPasswordRequest, ResetPasswordResponse, VerifyEmailRequest, VerifyEmailResponse, ResendVerificationRequest, ResendVerificationResponse, AllyCode, AllyCodeCreate, AllyCodeListResponse, AllyCodeMigrationPrompt, } from './user';
|
|
1
|
+
export type { User, LoginRequest, LoginResponse, RegisterRequest, RegisterResponse, RefreshTokenRequest, RefreshTokenResponse, ForgotPasswordRequest, ForgotPasswordResponse, ResetPasswordRequest, ResetPasswordResponse, VerifyEmailRequest, VerifyEmailResponse, ResendVerificationRequest, ResendVerificationResponse, AllyCode, AllyCodeCreate, AllyCodeListResponse, AllyCodeMigrationPrompt, TokenResponse, UpdateAccountRequest, UpdateAccountResponse, LogoutAllResponse, } from './user';
|
|
2
2
|
export type { ApiResponse, ApiError, PaginatedResponse } from './api';
|
|
3
3
|
export type { ModStat, ParsedMod, ModListResponse, EvaluationScores, ModEvaluation, EvaluationRequest, EvaluationResponse, } from './mod';
|
package/dist/src/types/user.d.ts
CHANGED
|
@@ -86,3 +86,27 @@ export interface AllyCodeMigrationPrompt {
|
|
|
86
86
|
show: boolean;
|
|
87
87
|
localStorageCodes: string[];
|
|
88
88
|
}
|
|
89
|
+
export interface TokenResponse {
|
|
90
|
+
access_token: string;
|
|
91
|
+
refresh_token: string;
|
|
92
|
+
token_type: string;
|
|
93
|
+
expires_in: number;
|
|
94
|
+
}
|
|
95
|
+
export interface UpdateAccountRequest {
|
|
96
|
+
email?: string;
|
|
97
|
+
/** Required by the backend whenever `email` or `new_password` is set. */
|
|
98
|
+
current_password?: string;
|
|
99
|
+
new_password?: string;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* PATCH /users/me response. `tokens` is set only when the email or password
|
|
103
|
+
* actually changed — that revokes every outstanding token for the account
|
|
104
|
+
* (including the caller's own), so fresh ones come back here. `null` means
|
|
105
|
+
* nothing changed (a no-op body, or the same email re-submitted).
|
|
106
|
+
*/
|
|
107
|
+
export interface UpdateAccountResponse extends User {
|
|
108
|
+
tokens: TokenResponse | null;
|
|
109
|
+
}
|
|
110
|
+
export interface LogoutAllResponse {
|
|
111
|
+
message: string;
|
|
112
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "astrogators-shared-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"description": "Shared UI components and utilities for Astrogator's Table applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -23,7 +23,9 @@
|
|
|
23
23
|
"dev": "vite",
|
|
24
24
|
"build": "tsc && vite build",
|
|
25
25
|
"preview": "vite preview",
|
|
26
|
-
"type-check": "tsc --noEmit"
|
|
26
|
+
"type-check": "tsc --noEmit",
|
|
27
|
+
"test": "vitest run",
|
|
28
|
+
"prepublishOnly": "npm run type-check && npm test"
|
|
27
29
|
},
|
|
28
30
|
"repository": {
|
|
29
31
|
"type": "git",
|
|
@@ -48,8 +50,8 @@
|
|
|
48
50
|
"react": "^19.2.5",
|
|
49
51
|
"react-dom": "^19.2.5",
|
|
50
52
|
"typescript": "^6.0.3",
|
|
51
|
-
"vite": "^8.0
|
|
52
|
-
"vite-plugin-dts": "^4.5.4"
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
"vite": "^8.3.0",
|
|
54
|
+
"vite-plugin-dts": "^4.5.4",
|
|
55
|
+
"vitest": "^5.0.1"
|
|
56
|
+
}
|
|
55
57
|
}
|