astrogators-shared-ui 0.5.0 → 0.6.1

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.
Files changed (30) hide show
  1. package/README.md +137 -203
  2. package/dist/index.css +2 -0
  3. package/dist/index.js +744 -805
  4. package/dist/{components → src/components}/display/Badge.d.ts +0 -1
  5. package/dist/{components → src/components}/display/Card.d.ts +0 -1
  6. package/dist/{components → src/components}/display/Modal.d.ts +0 -1
  7. package/dist/{components → src/components}/feedback/Loader.d.ts +0 -1
  8. package/dist/{components → src/components}/forms/AllyCodeDropdown.d.ts +0 -1
  9. package/dist/{components → src/components}/forms/Button.d.ts +0 -1
  10. package/dist/{components → src/components}/forms/Input.d.ts +0 -1
  11. package/dist/{components → src/components}/forms/Select.d.ts +0 -1
  12. package/dist/{components → src/components}/layout/Container.d.ts +0 -1
  13. package/dist/{components → src/components}/layout/Footer.d.ts +0 -1
  14. package/dist/{components → src/components}/layout/TopBar.d.ts +0 -1
  15. package/dist/{contexts → src/contexts}/AuthContext.d.ts +0 -1
  16. package/dist/{index.d.ts → src/index.d.ts} +0 -1
  17. package/package.json +18 -13
  18. package/dist/style.css +0 -1
  19. /package/dist/{components → src/components}/display/index.d.ts +0 -0
  20. /package/dist/{components → src/components}/feedback/index.d.ts +0 -0
  21. /package/dist/{components → src/components}/forms/index.d.ts +0 -0
  22. /package/dist/{components → src/components}/layout/index.d.ts +0 -0
  23. /package/dist/{services → src/services}/allyCodeStorage.d.ts +0 -0
  24. /package/dist/{services → src/services}/api.d.ts +0 -0
  25. /package/dist/{services → src/services}/auth.d.ts +0 -0
  26. /package/dist/{types → src/types}/api.d.ts +0 -0
  27. /package/dist/{types → src/types}/index.d.ts +0 -0
  28. /package/dist/{types → src/types}/mod.d.ts +0 -0
  29. /package/dist/{types → src/types}/user.d.ts +0 -0
  30. /package/dist/{utils → src/utils}/formatAllyCode.d.ts +0 -0
package/dist/index.js CHANGED
@@ -1,805 +1,744 @@
1
- var ye = Object.defineProperty;
2
- var pe = (e, t, s) => t in e ? ye(e, t, { enumerable: !0, configurable: !0, writable: !0, value: s }) : e[t] = s;
3
- var j = (e, t, s) => pe(e, typeof t != "symbol" ? t + "" : t, s);
4
- import { jsx as a, jsxs as m, Fragment as ve } from "react/jsx-runtime";
5
- import le, { createContext as be, useState as b, useEffect as I, useCallback as S, useContext as $e } from "react";
6
- const we = "_container_u3o0e_1", Ne = "_padding_u3o0e_7", ee = {
7
- container: we,
8
- padding: Ne,
9
- "maxWidth-sm": "_maxWidth-sm_u3o0e_12",
10
- "maxWidth-md": "_maxWidth-md_u3o0e_16",
11
- "maxWidth-lg": "_maxWidth-lg_u3o0e_20",
12
- "maxWidth-xl": "_maxWidth-xl_u3o0e_24",
13
- "maxWidth-full": "_maxWidth-full_u3o0e_28"
14
- }, Ns = ({
15
- children: e,
16
- maxWidth: t = "xl",
17
- padding: s = !0,
18
- className: o = "",
19
- style: c
20
- }) => /* @__PURE__ */ a(
21
- "div",
22
- {
23
- className: `${ee.container} ${ee[`maxWidth-${t}`]} ${s ? ee.padding : ""} ${o}`,
24
- style: c,
25
- children: e
26
- }
27
- ), Ae = "_topBar_10g3c_1", Se = "_content_10g3c_13", xe = "_left_10g3c_23", Te = "_right_10g3c_30", Ce = "_logo_10g3c_36", B = {
28
- topBar: Ae,
29
- content: Se,
30
- left: xe,
31
- right: Te,
32
- logo: Ce
33
- }, As = ({
34
- logo: e,
35
- leftContent: t,
36
- rightContent: s,
37
- className: o = ""
38
- }) => /* @__PURE__ */ a("header", { className: `${B.topBar} ${o}`, children: /* @__PURE__ */ m("div", { className: B.content, children: [
39
- /* @__PURE__ */ m("div", { className: B.left, children: [
40
- e && /* @__PURE__ */ a("div", { className: B.logo, children: e }),
41
- t
42
- ] }),
43
- /* @__PURE__ */ a("div", { className: B.right, children: s })
44
- ] }) }), ke = "_footer_zjuj8_1", Ee = "_content_zjuj8_7", Le = "_defaultContent_zjuj8_13", We = "_copyright_zjuj8_21", Ie = "_disclaimer_zjuj8_26", U = {
45
- footer: ke,
46
- content: Ee,
47
- defaultContent: Le,
48
- copyright: We,
49
- disclaimer: Ie
50
- }, Ss = ({ children: e, className: t = "" }) => /* @__PURE__ */ a("footer", { className: `${U.footer} ${t}`, children: /* @__PURE__ */ a("div", { className: U.content, children: e || /* @__PURE__ */ m("div", { className: U.defaultContent, children: [
51
- /* @__PURE__ */ m("p", { className: U.copyright, children: [
52
- ",
53
- (/* @__PURE__ */ new Date()).getFullYear(),
54
- " The Astrogator's Table. All rights reserved."
55
- ] }),
56
- /* @__PURE__ */ a("p", { className: U.disclaimer, children: "Star Wars: Galaxy of Heroes is a trademark of Electronic Arts Inc." })
57
- ] }) }) }), qe = "_button_159ms_1", Re = "_sm_159ms_22", Fe = "_md_159ms_28", Pe = "_lg_159ms_34", je = "_primary_159ms_41", Be = "_secondary_159ms_55", Ue = "_outline_159ms_69", De = "_ghost_159ms_80", Oe = "_danger_159ms_89", ze = "_fullWidth_159ms_100", Me = "_loading_159ms_105", Je = "_loadingSpinner_159ms_110", He = "_spinner_159ms_116", Ye = "_spin_159ms_116", Ge = "_loadingText_159ms_131", x = {
58
- button: qe,
59
- sm: Re,
60
- md: Fe,
61
- lg: Pe,
62
- primary: je,
63
- secondary: Be,
64
- outline: Ue,
65
- ghost: De,
66
- danger: Oe,
67
- fullWidth: ze,
68
- loading: Me,
69
- loadingSpinner: Je,
70
- spinner: He,
71
- spin: Ye,
72
- loadingText: Ge
73
- }, H = ({
74
- children: e,
75
- variant: t = "primary",
76
- size: s = "md",
77
- fullWidth: o = !1,
78
- loading: c = !1,
79
- disabled: g = !1,
80
- className: i = "",
81
- ...d
82
- }) => /* @__PURE__ */ a(
83
- "button",
84
- {
85
- className: `${x.button} ${x[t]} ${x[s]} ${o ? x.fullWidth : ""} ${c ? x.loading : ""} ${i}`,
86
- disabled: g || c,
87
- ...d,
88
- children: c ? /* @__PURE__ */ m("span", { className: x.loadingSpinner, children: [
89
- /* @__PURE__ */ a("span", { className: x.spinner }),
90
- /* @__PURE__ */ a("span", { className: x.loadingText, children: e })
91
- ] }) : e
92
- }
93
- ), Ke = "_inputWrapper_15t4g_1", Ve = "_fullWidth_15t4g_7", Qe = "_label_15t4g_11", Xe = "_required_15t4g_20", Ze = "_input_15t4g_1", et = "_error_15t4g_55", tt = "_errorText_15t4g_63", st = "_helperText_15t4g_68", T = {
94
- inputWrapper: Ke,
95
- fullWidth: Ve,
96
- label: Qe,
97
- required: Xe,
98
- input: Ze,
99
- error: et,
100
- errorText: tt,
101
- helperText: st
102
- }, ce = le.forwardRef(
103
- ({
104
- label: e,
105
- error: t,
106
- helperText: s,
107
- fullWidth: o = !1,
108
- className: c = "",
109
- id: g,
110
- ...i
111
- }, d) => {
112
- const l = g || `input-${Math.random().toString(36).substr(2, 9)}`, f = !!t;
113
- return /* @__PURE__ */ m("div", { className: `${T.inputWrapper} ${o ? T.fullWidth : ""} ${c}`, children: [
114
- e && /* @__PURE__ */ m("label", { htmlFor: l, className: T.label, children: [
115
- e,
116
- i.required && /* @__PURE__ */ a("span", { className: T.required, children: "*" })
117
- ] }),
118
- /* @__PURE__ */ a(
119
- "input",
120
- {
121
- ref: d,
122
- id: l,
123
- className: `${T.input} ${f ? T.error : ""}`,
124
- ...i
125
- }
126
- ),
127
- t && /* @__PURE__ */ a("span", { className: T.errorText, children: t }),
128
- s && !t && /* @__PURE__ */ a("span", { className: T.helperText, children: s })
129
- ] });
130
- }
131
- );
132
- ce.displayName = "Input";
133
- const ot = "_selectWrapper_ir4bq_1", rt = "_fullWidth_ir4bq_7", at = "_label_ir4bq_11", nt = "_required_ir4bq_20", lt = "_selectContainer_ir4bq_24", ct = "_select_ir4bq_1", it = "_error_ir4bq_63", dt = "_arrow_ir4bq_71", _t = "_errorText_ir4bq_81", mt = "_helperText_ir4bq_86", w = {
134
- selectWrapper: ot,
135
- fullWidth: rt,
136
- label: at,
137
- required: nt,
138
- selectContainer: lt,
139
- select: ct,
140
- error: it,
141
- arrow: dt,
142
- errorText: _t,
143
- helperText: mt
144
- }, ie = le.forwardRef(
145
- ({
146
- label: e,
147
- error: t,
148
- helperText: s,
149
- options: o,
150
- placeholder: c,
151
- fullWidth: g = !1,
152
- className: i = "",
153
- id: d,
154
- ...l
155
- }, f) => {
156
- const h = d || `select-${Math.random().toString(36).substr(2, 9)}`, y = !!t;
157
- return /* @__PURE__ */ m("div", { className: `${w.selectWrapper} ${g ? w.fullWidth : ""} ${i}`, children: [
158
- e && /* @__PURE__ */ m("label", { htmlFor: h, className: w.label, children: [
159
- e,
160
- l.required && /* @__PURE__ */ a("span", { className: w.required, children: "*" })
161
- ] }),
162
- /* @__PURE__ */ m("div", { className: w.selectContainer, children: [
163
- /* @__PURE__ */ m(
164
- "select",
165
- {
166
- ref: f,
167
- id: h,
168
- className: `${w.select} ${y ? w.error : ""}`,
169
- ...l,
170
- children: [
171
- c && /* @__PURE__ */ a("option", { value: "", disabled: !0, children: c }),
172
- o && o.map((p) => /* @__PURE__ */ a(
173
- "option",
174
- {
175
- value: p.value,
176
- disabled: p.disabled,
177
- children: p.label
178
- },
179
- p.value
180
- )),
181
- !o && l.children
182
- ]
183
- }
184
- ),
185
- /* @__PURE__ */ a("span", { className: w.arrow, children: "▼" })
186
- ] }),
187
- t && /* @__PURE__ */ a("span", { className: w.errorText, children: t }),
188
- s && !t && /* @__PURE__ */ a("span", { className: w.helperText, children: s })
189
- ] });
190
- }
191
- );
192
- ie.displayName = "Select";
193
- const oe = "astrogators_access_token", re = "astrogators_refresh_token", de = () => localStorage.getItem(oe), ut = (e) => {
194
- localStorage.setItem(oe, e);
195
- }, ht = () => {
196
- localStorage.removeItem(oe);
197
- }, gt = () => localStorage.getItem(re), ft = (e) => {
198
- localStorage.setItem(re, e);
199
- }, yt = () => {
200
- localStorage.removeItem(re);
201
- }, _e = (e, t) => {
202
- ut(e), ft(t);
203
- }, se = () => {
204
- ht(), yt();
205
- }, pt = () => !!de();
206
- class vt {
207
- constructor(t) {
208
- j(this, "baseURL");
209
- j(this, "onUnauthorized");
210
- j(this, "isRefreshing", !1);
211
- j(this, "refreshPromise", null);
212
- this.baseURL = t.baseURL, this.onUnauthorized = t.onUnauthorized;
213
- }
214
- async refreshAccessToken() {
215
- var c;
216
- const t = gt();
217
- if (!t)
218
- throw new Error("No refresh token available");
219
- const s = await fetch(`${this.baseURL}/api/v1/auth/refresh-token`, {
220
- method: "POST",
221
- headers: {
222
- "Content-Type": "application/json"
223
- },
224
- body: JSON.stringify({ refresh_token: t })
225
- });
226
- if (!s.ok)
227
- throw se(), (c = this.onUnauthorized) == null || c.call(this), new Error("Token refresh failed");
228
- const o = await s.json();
229
- return _e(o.access_token, t), o.access_token;
230
- }
231
- async request(t, s = {}) {
232
- const o = de(), c = {
233
- "Content-Type": "application/json",
234
- ...s.headers
235
- };
236
- o && (c.Authorization = `Bearer ${o}`);
237
- const g = `${this.baseURL}${t}`;
238
- let i = await fetch(g, {
239
- ...s,
240
- headers: c
241
- });
242
- if (i.status === 401 && o) {
243
- this.isRefreshing || (this.isRefreshing = !0, this.refreshPromise = this.refreshAccessToken().finally(() => {
244
- this.isRefreshing = !1, this.refreshPromise = null;
245
- }));
246
- try {
247
- const d = await this.refreshPromise;
248
- c.Authorization = `Bearer ${d}`, i = await fetch(g, {
249
- ...s,
250
- headers: c
251
- });
252
- } catch {
253
- throw new Error("Authentication failed");
254
- }
255
- }
256
- if (!i.ok) {
257
- const d = {
258
- message: i.statusText,
259
- status: i.status
260
- };
261
- try {
262
- const l = await i.json();
263
- if (i.status === 422 && Array.isArray(l.detail)) {
264
- const f = l.detail.map((h) => h.msg || "Validation error").join(", ");
265
- d.message = f;
266
- } else typeof l.detail == "string" ? d.message = l.detail : l.message && (d.message = l.message);
267
- d.detail = l.detail;
268
- } catch {
269
- }
270
- throw d;
271
- }
272
- return i.status === 204 ? {} : i.json();
273
- }
274
- async get(t, s) {
275
- return this.request(t, { ...s, method: "GET" });
276
- }
277
- async post(t, s, o) {
278
- return this.request(t, {
279
- ...o,
280
- method: "POST",
281
- body: s ? JSON.stringify(s) : void 0
282
- });
283
- }
284
- async put(t, s, o) {
285
- return this.request(t, {
286
- ...o,
287
- method: "PUT",
288
- body: s ? JSON.stringify(s) : void 0
289
- });
290
- }
291
- async patch(t, s, o) {
292
- return this.request(t, {
293
- ...o,
294
- method: "PATCH",
295
- body: s ? JSON.stringify(s) : void 0
296
- });
297
- }
298
- async delete(t, s) {
299
- return this.request(t, { ...s, method: "DELETE" });
300
- }
301
- }
302
- let v;
303
- const bt = (e) => {
304
- v = new vt(e);
305
- }, O = "astrogators_ally_codes", G = "astrogators_selected_ally_code", A = () => {
306
- try {
307
- const e = localStorage.getItem(O);
308
- return e ? JSON.parse(e) : [];
309
- } catch (e) {
310
- return console.error("Failed to read ally codes from localStorage:", e), [];
311
- }
312
- }, $t = (e) => {
313
- try {
314
- const t = A();
315
- if (t.some((o) => o.ally_code === e.ally_code))
316
- return;
317
- t.push(e), localStorage.setItem(O, JSON.stringify(t));
318
- } catch (t) {
319
- console.error("Failed to save ally code to localStorage:", t);
320
- }
321
- }, wt = (e) => {
322
- try {
323
- const s = A().filter((o) => o.ally_code !== e);
324
- localStorage.setItem(O, JSON.stringify(s));
325
- } catch (t) {
326
- console.error("Failed to remove ally code from localStorage:", t);
327
- }
328
- }, ne = (e) => {
329
- try {
330
- const s = A().map(
331
- (o) => o.ally_code === e ? { ...o, last_used_at: (/* @__PURE__ */ new Date()).toISOString() } : o
332
- );
333
- localStorage.setItem(O, JSON.stringify(s));
334
- } catch (t) {
335
- console.error("Failed to update ally code last used:", t);
336
- }
337
- }, Nt = () => localStorage.getItem(G), At = (e) => {
338
- e ? localStorage.setItem(G, e) : localStorage.removeItem(G);
339
- }, St = () => {
340
- localStorage.removeItem(O), localStorage.removeItem(G);
341
- }, me = be(void 0), xs = ({ children: e, apiBaseUrl: t }) => {
342
- const [s, o] = b(null), [c, g] = b(!0), [i, d] = b(!0), [l, f] = b(!0), [h, y] = b([]), [p, k] = b(null), [z, L] = b(!1), [M, W] = b({
343
- show: !1,
344
- localStorageCodes: []
345
- });
346
- I(() => {
347
- bt({
348
- baseURL: t
349
- });
350
- }, [t]), I(() => {
351
- (async () => {
352
- try {
353
- const n = await v.get("/api/v1/config/features");
354
- d(n.auth_enabled);
355
- } catch (n) {
356
- console.error("Failed to fetch features:", n), d(!0);
357
- } finally {
358
- f(!1);
359
- }
360
- })();
361
- }, [t]);
362
- const q = S(async () => {
363
- if (!pt()) {
364
- o(null), g(!1);
365
- return;
366
- }
367
- try {
368
- const r = await v.get("/api/v1/users/me");
369
- o(r);
370
- } catch (r) {
371
- console.error("Failed to fetch user:", r), o(null), se();
372
- } finally {
373
- g(!1);
374
- }
375
- }, []);
376
- I(() => {
377
- q();
378
- }, [q]);
379
- const K = async (r) => {
380
- try {
381
- const n = await v.post("/api/v1/auth/login", r);
382
- _e(n.access_token, n.refresh_token);
383
- const u = await v.get("/api/v1/users/me");
384
- o(u);
385
- } catch (n) {
386
- throw console.error("Login failed:", n), n;
387
- }
388
- }, V = async (r) => {
389
- try {
390
- await v.post("/api/v1/auth/register", r);
391
- } catch (n) {
392
- throw console.error("Registration failed:", n), n;
393
- }
394
- }, Q = () => {
395
- se(), o(null), y([]), k(null), W({ show: !1, localStorageCodes: [] });
396
- }, _ = async () => {
397
- await q();
398
- }, N = async (r) => {
399
- try {
400
- return (await v.post(
401
- "/api/v1/auth/forgot-password",
402
- r
403
- )).message;
404
- } catch (n) {
405
- throw console.error("Forgot password failed:", n), n;
406
- }
407
- }, R = async (r) => {
408
- try {
409
- return (await v.post(
410
- "/api/v1/auth/reset-password",
411
- r
412
- )).message;
413
- } catch (n) {
414
- throw console.error("Reset password failed:", n), n;
415
- }
416
- }, ue = async (r) => {
417
- try {
418
- return (await v.post(
419
- "/api/v1/auth/resend-verification",
420
- r
421
- )).message;
422
- } catch (n) {
423
- throw console.error("Resend verification failed:", n), n;
424
- }
425
- }, F = S(async () => {
426
- L(!0);
427
- try {
428
- if (s) {
429
- const n = await v.get("/api/v1/users/me/ally-codes");
430
- y(n.ally_codes);
431
- const u = A();
432
- u.length > 0 && W({
433
- show: !0,
434
- localStorageCodes: u.map((P) => P.ally_code)
435
- });
436
- } else {
437
- const n = A();
438
- y(n);
439
- }
440
- const r = Nt();
441
- k(r);
442
- } catch (r) {
443
- console.error("Failed to fetch ally codes:", r), y([]);
444
- } finally {
445
- L(!1);
446
- }
447
- }, [s]), X = S(async (r) => {
448
- var n;
449
- if (!/^\d{9}$/.test(r))
450
- throw new Error("Ally code must be exactly 9 digits");
451
- if (s) {
452
- const u = await v.post(
453
- "/api/v1/users/me/ally-codes",
454
- { ally_code: r }
455
- );
456
- y((P) => [u, ...P]), h.length === 0 && J(r);
457
- } else {
458
- const u = await v.get(`/api/v1/player-data/player/${r}`);
459
- if (!u)
460
- throw new Error("Invalid ally code - player not found");
461
- const P = {
462
- ally_code: r,
463
- player_name: ((n = u == null ? void 0 : u.data) == null ? void 0 : n.name) || null,
464
- last_used_at: (/* @__PURE__ */ new Date()).toISOString()
465
- };
466
- $t(P), y(A()), h.length === 0 && J(r);
467
- }
468
- }, [s, h.length]), he = S(async (r) => {
469
- s && typeof r == "number" ? (await v.delete(`/api/v1/users/me/ally-codes/${r}`), y((n) => n.filter((u) => "id" in u && u.id !== r))) : !s && typeof r == "string" && (wt(r), y(A()), p === r && J(null));
470
- }, [s, p]), J = S((r) => {
471
- if (k(r), At(r), r && s) {
472
- const n = h.find((u) => "ally_code" in u && u.ally_code === r);
473
- n && "id" in n && ae(n.id);
474
- } else r && !s && ne(r);
475
- }, [s, h]), ae = S(async (r) => {
476
- s && typeof r == "number" ? (await v.put(`/api/v1/users/me/ally-codes/${r}/use`, {}), await F()) : !s && typeof r == "string" && (ne(r), y(A()));
477
- }, [s, F]), Z = S(() => {
478
- W({ show: !1, localStorageCodes: [] });
479
- }, []), ge = S(async () => {
480
- if (!s) return;
481
- const r = A();
482
- for (const n of r)
483
- try {
484
- await X(n.ally_code);
485
- } catch (u) {
486
- console.error(`Failed to migrate ally code ${n.ally_code}:`, u);
487
- }
488
- St(), Z();
489
- }, [s, X, Z]);
490
- I(() => {
491
- F();
492
- }, [F]);
493
- const fe = {
494
- user: s,
495
- isAuthenticated: !!s,
496
- isLoading: c,
497
- login: K,
498
- register: V,
499
- logout: Q,
500
- refreshUser: _,
501
- forgotPassword: N,
502
- resetPassword: R,
503
- resendVerification: ue,
504
- // Feature flags
505
- authEnabled: i,
506
- isLoadingFeatures: l,
507
- // Ally code values
508
- allyCodes: h,
509
- selectedAllyCode: p,
510
- isLoadingAllyCodes: z,
511
- fetchAllyCodes: F,
512
- addAllyCode: X,
513
- removeAllyCode: he,
514
- selectAllyCode: J,
515
- updateAllyCodeLastUsed: ae,
516
- migrationPrompt: M,
517
- dismissMigrationPrompt: Z,
518
- migrateLocalStorageCodes: ge
519
- };
520
- return /* @__PURE__ */ a(me.Provider, { value: fe, children: e });
521
- }, xt = () => {
522
- const e = $e(me);
523
- if (e === void 0)
524
- throw new Error("useAuth must be used within an AuthProvider");
525
- return e;
526
- }, Y = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e.slice(6, 9)}`, Ts = (e) => e.replace(/-/g, ""), Tt = "_allyCodeDropdown_1m0tw_1", Ct = "_select_1m0tw_8", kt = "_manageButton_1m0tw_12", Et = "_managePanel_1m0tw_16", Lt = "_addSection_1m0tw_37", Wt = "_addInputGroup_1m0tw_43", It = "_error_1m0tw_55", qt = "_success_1m0tw_61", Rt = "_codesList_1m0tw_67", Ft = "_codeItem_1m0tw_71", Pt = "_doneButton_1m0tw_88", $ = {
527
- allyCodeDropdown: Tt,
528
- select: Ct,
529
- manageButton: kt,
530
- managePanel: Et,
531
- addSection: Lt,
532
- addInputGroup: Wt,
533
- error: It,
534
- success: qt,
535
- codesList: Rt,
536
- codeItem: Ft,
537
- doneButton: Pt
538
- }, Cs = ({
539
- onAllyCodeSelected: e,
540
- className: t = ""
541
- }) => {
542
- const {
543
- allyCodes: s,
544
- selectedAllyCode: o,
545
- selectAllyCode: c,
546
- removeAllyCode: g,
547
- addAllyCode: i,
548
- isLoadingAllyCodes: d
549
- } = xt(), [l, f] = b(!1), [h, y] = b(""), [p, k] = b(""), [z, L] = b(""), [M, W] = b(!1), q = s.map((_) => ({
550
- value: _.ally_code,
551
- label: _.player_name ? `${_.player_name} (${Y(_.ally_code)})` : Y(_.ally_code)
552
- })), K = (_) => {
553
- const N = _.target.value || null;
554
- c(N), e == null || e(N);
555
- }, V = async (_) => {
556
- const N = s.find((R) => R.ally_code === _);
557
- if (N) {
558
- const R = "id" in N ? N.id : N.ally_code;
559
- await g(R);
560
- }
561
- }, Q = async () => {
562
- if (k(""), L(""), !/^\d{9}$/.test(h)) {
563
- k("Ally code must be exactly 9 digits");
564
- return;
565
- }
566
- W(!0);
567
- try {
568
- await i(h), L("Added successfully!"), y(""), setTimeout(() => L(""), 2e3);
569
- } catch (_) {
570
- k(_.message || "Failed to add ally code");
571
- } finally {
572
- W(!1);
573
- }
574
- };
575
- return s.length === 0 ? null : /* @__PURE__ */ m("div", { className: `${$.allyCodeDropdown} ${t}`, children: [
576
- /* @__PURE__ */ a(
577
- ie,
578
- {
579
- options: q,
580
- value: o || "",
581
- onChange: K,
582
- placeholder: "Select ally code",
583
- disabled: d,
584
- className: $.select
585
- }
586
- ),
587
- l && /* @__PURE__ */ m("div", { className: $.managePanel, children: [
588
- /* @__PURE__ */ a("h4", { children: "Manage Ally Codes" }),
589
- /* @__PURE__ */ m("div", { className: $.addSection, children: [
590
- /* @__PURE__ */ m("div", { className: $.addInputGroup, children: [
591
- /* @__PURE__ */ a(
592
- ce,
593
- {
594
- type: "text",
595
- placeholder: "9-digit ally code",
596
- value: h,
597
- onChange: (_) => y(_.target.value.replace(/\D/g, "").slice(0, 9)),
598
- disabled: M
599
- }
600
- ),
601
- /* @__PURE__ */ a(
602
- H,
603
- {
604
- variant: "primary",
605
- size: "sm",
606
- onClick: Q,
607
- loading: M,
608
- disabled: h.length !== 9,
609
- children: "Add"
610
- }
611
- )
612
- ] }),
613
- p && /* @__PURE__ */ a("div", { className: $.error, children: p }),
614
- z && /* @__PURE__ */ a("div", { className: $.success, children: z })
615
- ] }),
616
- /* @__PURE__ */ a("div", { className: $.codesList, children: s.map((_) => /* @__PURE__ */ m("div", { className: $.codeItem, children: [
617
- /* @__PURE__ */ a("span", { children: _.player_name ? `${_.player_name} (${Y(_.ally_code)})` : Y(_.ally_code) }),
618
- /* @__PURE__ */ a(
619
- H,
620
- {
621
- variant: "ghost",
622
- size: "sm",
623
- onClick: () => V(_.ally_code),
624
- children: "Remove"
625
- }
626
- )
627
- ] }, _.ally_code)) }),
628
- /* @__PURE__ */ a(
629
- H,
630
- {
631
- variant: "secondary",
632
- size: "sm",
633
- onClick: () => f(!1),
634
- className: $.doneButton,
635
- children: "Done"
636
- }
637
- )
638
- ] }),
639
- /* @__PURE__ */ a(
640
- H,
641
- {
642
- variant: "ghost",
643
- size: "sm",
644
- onClick: () => f(!l),
645
- className: $.manageButton,
646
- children: "Manage"
647
- }
648
- )
649
- ] });
650
- }, jt = "_card_b4471_1", Bt = "_chamfered_b4471_8", Ut = "_elevated_b4471_17", Dt = "_outline_b4471_22", Ot = "_hoverable_b4471_45", D = {
651
- card: jt,
652
- chamfered: Bt,
653
- default: "_default_b4471_13",
654
- elevated: Ut,
655
- outline: Dt,
656
- "padding-none": "_padding-none_b4471_28",
657
- "padding-sm": "_padding-sm_b4471_32",
658
- "padding-md": "_padding-md_b4471_36",
659
- "padding-lg": "_padding-lg_b4471_40",
660
- hoverable: Ot
661
- }, ks = ({
662
- children: e,
663
- variant: t = "default",
664
- chamfered: s = !1,
665
- chamferSize: o = "md",
666
- padding: c = "md",
667
- hoverable: g = !1,
668
- showDiagonalBorders: i = !1,
669
- diagonalBorderColor: d,
670
- className: l = "",
671
- onClick: f,
672
- style: h
673
- }) => {
674
- const y = s ? o === "asymmetric" ? "chamfered-box-asymmetric" : o === "sm" ? "chamfered-box-sm" : o === "lg" ? "chamfered-box-lg" : "chamfered-box" : "", p = d ? { color: d } : void 0;
675
- return /* @__PURE__ */ m(
676
- "div",
677
- {
678
- className: `${D.card} ${s ? D.chamfered : ""} ${D[t]} ${D[`padding-${c}`]} ${y} ${g ? D.hoverable : ""} ${l}`,
679
- onClick: f,
680
- role: f ? "button" : void 0,
681
- tabIndex: f ? 0 : void 0,
682
- style: h,
683
- children: [
684
- i && /* @__PURE__ */ m(ve, { children: [
685
- /* @__PURE__ */ a("div", { className: "chamfered-diagonal-border chamfered-diagonal-tl", style: p }),
686
- /* @__PURE__ */ a("div", { className: "chamfered-diagonal-border chamfered-diagonal-tr", style: p }),
687
- /* @__PURE__ */ a("div", { className: "chamfered-diagonal-border chamfered-diagonal-bl", style: p }),
688
- /* @__PURE__ */ a("div", { className: `chamfered-diagonal-border ${o === "asymmetric" ? "chamfered-diagonal-br-large" : "chamfered-diagonal-br"}`, style: p })
689
- ] }),
690
- e
691
- ]
692
- }
693
- );
694
- }, zt = "_badge_rk7t5_1", Mt = "_sm_rk7t5_11", Jt = "_md_rk7t5_16", Ht = "_lg_rk7t5_21", Yt = "_primary_rk7t5_32", Gt = "_secondary_rk7t5_37", Kt = "_success_rk7t5_42", Vt = "_warning_rk7t5_47", Qt = "_error_rk7t5_52", Xt = "_info_rk7t5_57", te = {
695
- badge: zt,
696
- sm: Mt,
697
- md: Jt,
698
- lg: Ht,
699
- default: "_default_rk7t5_27",
700
- primary: Yt,
701
- secondary: Gt,
702
- success: Kt,
703
- warning: Vt,
704
- error: Qt,
705
- info: Xt
706
- }, Es = ({
707
- children: e,
708
- variant: t = "default",
709
- size: s = "md",
710
- className: o = ""
711
- }) => /* @__PURE__ */ a("span", { className: `${te.badge} ${te[t]} ${te[s]} ${o}`, children: e }), Zt = "_overlay_1b3yt_1", es = "_fadeIn_1b3yt_1", ts = "_modal_1b3yt_13", ss = "_slideUp_1b3yt_1", os = "_sm_1b3yt_25", rs = "_md_1b3yt_30", as = "_lg_1b3yt_35", ns = "_xl_1b3yt_40", ls = "_header_1b3yt_45", cs = "_title_1b3yt_53", is = "_closeButton_1b3yt_60", ds = "_content_1b3yt_78", E = {
712
- overlay: Zt,
713
- fadeIn: es,
714
- modal: ts,
715
- slideUp: ss,
716
- sm: os,
717
- md: rs,
718
- lg: as,
719
- xl: ns,
720
- header: ls,
721
- title: cs,
722
- closeButton: is,
723
- content: ds
724
- }, Ls = ({
725
- isOpen: e,
726
- onClose: t,
727
- title: s,
728
- children: o,
729
- size: c = "md",
730
- closeOnOverlayClick: g = !0,
731
- className: i = ""
732
- }) => {
733
- if (I(() => (e ? document.body.style.overflow = "hidden" : document.body.style.overflow = "unset", () => {
734
- document.body.style.overflow = "unset";
735
- }), [e]), I(() => {
736
- const l = (f) => {
737
- f.key === "Escape" && e && t();
738
- };
739
- return document.addEventListener("keydown", l), () => document.removeEventListener("keydown", l);
740
- }, [e, t]), !e) return null;
741
- const d = (l) => {
742
- g && l.target === l.currentTarget && t();
743
- };
744
- return /* @__PURE__ */ a("div", { className: E.overlay, onClick: d, children: /* @__PURE__ */ m("div", { className: `${E.modal} ${E[c]} ${i}`, role: "dialog", "aria-modal": "true", children: [
745
- s && /* @__PURE__ */ m("div", { className: E.header, children: [
746
- /* @__PURE__ */ a("h2", { className: E.title, children: s }),
747
- /* @__PURE__ */ a("button", { className: E.closeButton, onClick: t, "aria-label": "Close modal", children: "✕" })
748
- ] }),
749
- /* @__PURE__ */ a("div", { className: E.content, children: o })
750
- ] }) });
751
- }, _s = "_spinner_1uhnh_2", ms = "_spin_1uhnh_2", us = "_sm_1uhnh_9", hs = "_md_1uhnh_15", gs = "_lg_1uhnh_21", fs = "_dots_1uhnh_34", ys = "_dot_1uhnh_34", ps = "_bounce_1uhnh_1", vs = "_visuallyHidden_1uhnh_91", C = {
752
- spinner: _s,
753
- spin: ms,
754
- sm: us,
755
- md: hs,
756
- lg: gs,
757
- dots: fs,
758
- dot: ys,
759
- bounce: ps,
760
- visuallyHidden: vs
761
- }, Ws = ({
762
- size: e = "md",
763
- variant: t = "spinner",
764
- className: s = ""
765
- }) => t === "dots" ? /* @__PURE__ */ m("div", { className: `${C.dots} ${C[e]} ${s}`, children: [
766
- /* @__PURE__ */ a("span", { className: C.dot }),
767
- /* @__PURE__ */ a("span", { className: C.dot }),
768
- /* @__PURE__ */ a("span", { className: C.dot })
769
- ] }) : /* @__PURE__ */ a("div", { className: `${C.spinner} ${C[e]} ${s}`, role: "status", children: /* @__PURE__ */ a("span", { className: C.visuallyHidden, children: "Loading..." }) });
770
- export {
771
- Cs as AllyCodeDropdown,
772
- vt as ApiClient,
773
- xs as AuthProvider,
774
- Es as Badge,
775
- H as Button,
776
- ks as Card,
777
- Ns as Container,
778
- Ss as Footer,
779
- ce as Input,
780
- Ws as Loader,
781
- Ls as Modal,
782
- ie as Select,
783
- As as TopBar,
784
- v as apiClient,
785
- St as clearAllyCodes,
786
- se as clearTokens,
787
- Y as formatAllyCode,
788
- de as getAccessToken,
789
- A as getAllyCodesFromStorage,
790
- gt as getRefreshToken,
791
- Nt as getSelectedAllyCode,
792
- bt as initializeApiClient,
793
- pt as isAuthenticated,
794
- ht as removeAccessToken,
795
- wt as removeAllyCodeFromStorage,
796
- yt as removeRefreshToken,
797
- $t as saveAllyCodeToStorage,
798
- ut as setAccessToken,
799
- ft as setRefreshToken,
800
- At as setSelectedAllyCode,
801
- _e as setTokens,
802
- Ts as unformatAllyCode,
803
- ne as updateAllyCodeLastUsed,
804
- xt as useAuth
805
- };
1
+ import e, { createContext as t, useCallback as n, useContext as r, useEffect as i, useState as a } from "react";
2
+ import { Fragment as o, jsx as s, jsxs as c } from "react/jsx-runtime";
3
+ var l = {
4
+ container: "_container_u3o0e_1",
5
+ padding: "_padding_u3o0e_7",
6
+ "maxWidth-sm": "_maxWidth-sm_u3o0e_12",
7
+ "maxWidth-md": "_maxWidth-md_u3o0e_16",
8
+ "maxWidth-lg": "_maxWidth-lg_u3o0e_20",
9
+ "maxWidth-xl": "_maxWidth-xl_u3o0e_24",
10
+ "maxWidth-full": "_maxWidth-full_u3o0e_28"
11
+ }, u = ({ children: e, maxWidth: t = "xl", padding: n = !0, className: r = "", style: i }) => /* @__PURE__ */ s("div", {
12
+ className: `${l.container} ${l[`maxWidth-${t}`]} ${n ? l.padding : ""} ${r}`,
13
+ style: i,
14
+ children: e
15
+ }), d = {
16
+ topBar: "_topBar_10g3c_1",
17
+ content: "_content_10g3c_13",
18
+ left: "_left_10g3c_23",
19
+ right: "_right_10g3c_30",
20
+ logo: "_logo_10g3c_36"
21
+ }, f = ({ logo: e, leftContent: t, rightContent: n, className: r = "" }) => /* @__PURE__ */ s("header", {
22
+ className: `${d.topBar} ${r}`,
23
+ children: /* @__PURE__ */ c("div", {
24
+ className: d.content,
25
+ children: [/* @__PURE__ */ c("div", {
26
+ className: d.left,
27
+ children: [e && /* @__PURE__ */ s("div", {
28
+ className: d.logo,
29
+ children: e
30
+ }), t]
31
+ }), /* @__PURE__ */ s("div", {
32
+ className: d.right,
33
+ children: n
34
+ })]
35
+ })
36
+ }), p = {
37
+ footer: "_footer_zjuj8_1",
38
+ content: "_content_zjuj8_7",
39
+ defaultContent: "_defaultContent_zjuj8_13",
40
+ copyright: "_copyright_zjuj8_21",
41
+ disclaimer: "_disclaimer_zjuj8_26"
42
+ }, m = ({ children: e, className: t = "" }) => /* @__PURE__ */ s("footer", {
43
+ className: `${p.footer} ${t}`,
44
+ children: /* @__PURE__ */ s("div", {
45
+ className: p.content,
46
+ children: e || /* @__PURE__ */ c("div", {
47
+ className: p.defaultContent,
48
+ children: [/* @__PURE__ */ c("p", {
49
+ className: p.copyright,
50
+ children: [
51
+ ",
52
+ (/* @__PURE__ */ new Date()).getFullYear(),
53
+ " The Astrogator's Table. All rights reserved."
54
+ ]
55
+ }), /* @__PURE__ */ s("p", {
56
+ className: p.disclaimer,
57
+ children: "Star Wars: Galaxy of Heroes is a trademark of Electronic Arts Inc."
58
+ })]
59
+ })
60
+ })
61
+ }), h = {
62
+ button: "_button_159ms_1",
63
+ sm: "_sm_159ms_22",
64
+ md: "_md_159ms_28",
65
+ lg: "_lg_159ms_34",
66
+ primary: "_primary_159ms_41",
67
+ secondary: "_secondary_159ms_55",
68
+ outline: "_outline_159ms_69",
69
+ ghost: "_ghost_159ms_80",
70
+ danger: "_danger_159ms_89",
71
+ fullWidth: "_fullWidth_159ms_100",
72
+ loading: "_loading_159ms_105",
73
+ loadingSpinner: "_loadingSpinner_159ms_110",
74
+ spinner: "_spinner_159ms_116",
75
+ spin: "_spin_159ms_116",
76
+ loadingText: "_loadingText_159ms_131"
77
+ }, g = ({ children: e, variant: t = "primary", size: n = "md", fullWidth: r = !1, loading: i = !1, disabled: a = !1, className: o = "", ...l }) => /* @__PURE__ */ s("button", {
78
+ className: `${h.button} ${h[t]} ${h[n]} ${r ? h.fullWidth : ""} ${i ? h.loading : ""} ${o}`,
79
+ disabled: a || i,
80
+ ...l,
81
+ children: i ? /* @__PURE__ */ c("span", {
82
+ className: h.loadingSpinner,
83
+ children: [/* @__PURE__ */ s("span", { className: h.spinner }), /* @__PURE__ */ s("span", {
84
+ className: h.loadingText,
85
+ children: e
86
+ })]
87
+ }) : e
88
+ }), _ = {
89
+ inputWrapper: "_inputWrapper_15t4g_1",
90
+ fullWidth: "_fullWidth_15t4g_7",
91
+ label: "_label_15t4g_11",
92
+ required: "_required_15t4g_20",
93
+ input: "_input_15t4g_1",
94
+ error: "_error_15t4g_55",
95
+ errorText: "_errorText_15t4g_63",
96
+ helperText: "_helperText_15t4g_68"
97
+ }, v = e.forwardRef(({ label: e, error: t, helperText: n, fullWidth: r = !1, className: i = "", id: a, ...o }, l) => {
98
+ let u = a || `input-${Math.random().toString(36).substr(2, 9)}`, d = !!t;
99
+ return /* @__PURE__ */ c("div", {
100
+ className: `${_.inputWrapper} ${r ? _.fullWidth : ""} ${i}`,
101
+ children: [
102
+ e && /* @__PURE__ */ c("label", {
103
+ htmlFor: u,
104
+ className: _.label,
105
+ children: [e, o.required && /* @__PURE__ */ s("span", {
106
+ className: _.required,
107
+ children: "*"
108
+ })]
109
+ }),
110
+ /* @__PURE__ */ s("input", {
111
+ ref: l,
112
+ id: u,
113
+ className: `${_.input} ${d ? _.error : ""}`,
114
+ ...o
115
+ }),
116
+ t && /* @__PURE__ */ s("span", {
117
+ className: _.errorText,
118
+ children: t
119
+ }),
120
+ n && !t && /* @__PURE__ */ s("span", {
121
+ className: _.helperText,
122
+ children: n
123
+ })
124
+ ]
125
+ });
126
+ });
127
+ v.displayName = "Input";
128
+ var y = {
129
+ selectWrapper: "_selectWrapper_ir4bq_1",
130
+ fullWidth: "_fullWidth_ir4bq_7",
131
+ label: "_label_ir4bq_11",
132
+ required: "_required_ir4bq_20",
133
+ selectContainer: "_selectContainer_ir4bq_24",
134
+ select: "_select_ir4bq_1",
135
+ error: "_error_ir4bq_63",
136
+ arrow: "_arrow_ir4bq_71",
137
+ errorText: "_errorText_ir4bq_81",
138
+ helperText: "_helperText_ir4bq_86"
139
+ }, b = e.forwardRef(({ label: e, error: t, helperText: n, options: r, placeholder: i, fullWidth: a = !1, className: o = "", id: l, ...u }, d) => {
140
+ let f = l || `select-${Math.random().toString(36).substr(2, 9)}`, p = !!t;
141
+ return /* @__PURE__ */ c("div", {
142
+ className: `${y.selectWrapper} ${a ? y.fullWidth : ""} ${o}`,
143
+ children: [
144
+ e && /* @__PURE__ */ c("label", {
145
+ htmlFor: f,
146
+ className: y.label,
147
+ children: [e, u.required && /* @__PURE__ */ s("span", {
148
+ className: y.required,
149
+ children: "*"
150
+ })]
151
+ }),
152
+ /* @__PURE__ */ c("div", {
153
+ className: y.selectContainer,
154
+ children: [/* @__PURE__ */ c("select", {
155
+ ref: d,
156
+ id: f,
157
+ className: `${y.select} ${p ? y.error : ""}`,
158
+ ...u,
159
+ children: [
160
+ i && /* @__PURE__ */ s("option", {
161
+ value: "",
162
+ disabled: !0,
163
+ children: i
164
+ }),
165
+ r && r.map((e) => /* @__PURE__ */ s("option", {
166
+ value: e.value,
167
+ disabled: e.disabled,
168
+ children: e.label
169
+ }, e.value)),
170
+ !r && u.children
171
+ ]
172
+ }), /* @__PURE__ */ s("span", {
173
+ className: y.arrow,
174
+ children: "▼"
175
+ })]
176
+ }),
177
+ t && /* @__PURE__ */ s("span", {
178
+ className: y.errorText,
179
+ children: t
180
+ }),
181
+ n && !t && /* @__PURE__ */ s("span", {
182
+ className: y.helperText,
183
+ children: n
184
+ })
185
+ ]
186
+ });
187
+ });
188
+ b.displayName = "Select";
189
+ //#endregion
190
+ //#region src/services/auth.ts
191
+ var x = "astrogators_access_token", S = "astrogators_refresh_token", C = () => localStorage.getItem(x), w = (e) => {
192
+ localStorage.setItem(x, e);
193
+ }, T = () => {
194
+ localStorage.removeItem(x);
195
+ }, E = () => localStorage.getItem(S), D = (e) => {
196
+ localStorage.setItem(S, e);
197
+ }, O = () => {
198
+ localStorage.removeItem(S);
199
+ }, k = (e, t) => {
200
+ w(e), D(t);
201
+ }, A = () => {
202
+ T(), O();
203
+ }, j = () => !!C(), M = class {
204
+ baseURL;
205
+ onUnauthorized;
206
+ isRefreshing = !1;
207
+ refreshPromise = null;
208
+ constructor(e) {
209
+ this.baseURL = e.baseURL, this.onUnauthorized = e.onUnauthorized;
210
+ }
211
+ async refreshAccessToken() {
212
+ let e = E();
213
+ if (!e) throw Error("No refresh token available");
214
+ let t = await fetch(`${this.baseURL}/api/v1/auth/refresh-token`, {
215
+ method: "POST",
216
+ headers: { "Content-Type": "application/json" },
217
+ body: JSON.stringify({ refresh_token: e })
218
+ });
219
+ if (!t.ok) throw A(), this.onUnauthorized?.(), Error("Token refresh failed");
220
+ let n = await t.json();
221
+ return k(n.access_token, e), n.access_token;
222
+ }
223
+ async request(e, t = {}) {
224
+ let n = C(), r = {
225
+ "Content-Type": "application/json",
226
+ ...t.headers
227
+ };
228
+ n && (r.Authorization = `Bearer ${n}`);
229
+ let i = `${this.baseURL}${e}`, a = await fetch(i, {
230
+ ...t,
231
+ headers: r
232
+ });
233
+ if (a.status === 401 && n) {
234
+ this.isRefreshing || (this.isRefreshing = !0, this.refreshPromise = this.refreshAccessToken().finally(() => {
235
+ this.isRefreshing = !1, this.refreshPromise = null;
236
+ }));
237
+ try {
238
+ r.Authorization = `Bearer ${await this.refreshPromise}`, a = await fetch(i, {
239
+ ...t,
240
+ headers: r
241
+ });
242
+ } catch {
243
+ throw Error("Authentication failed");
244
+ }
245
+ }
246
+ if (!a.ok) {
247
+ let e = {
248
+ message: a.statusText,
249
+ status: a.status
250
+ };
251
+ try {
252
+ let t = await a.json();
253
+ a.status === 422 && Array.isArray(t.detail) ? e.message = t.detail.map((e) => e.msg || "Validation error").join(", ") : typeof t.detail == "string" ? e.message = t.detail : t.message && (e.message = t.message), e.detail = t.detail;
254
+ } catch {}
255
+ throw e;
256
+ }
257
+ return a.status === 204 ? {} : a.json();
258
+ }
259
+ async get(e, t) {
260
+ return this.request(e, {
261
+ ...t,
262
+ method: "GET"
263
+ });
264
+ }
265
+ async post(e, t, n) {
266
+ return this.request(e, {
267
+ ...n,
268
+ method: "POST",
269
+ body: t ? JSON.stringify(t) : void 0
270
+ });
271
+ }
272
+ async put(e, t, n) {
273
+ return this.request(e, {
274
+ ...n,
275
+ method: "PUT",
276
+ body: t ? JSON.stringify(t) : void 0
277
+ });
278
+ }
279
+ async patch(e, t, n) {
280
+ return this.request(e, {
281
+ ...n,
282
+ method: "PATCH",
283
+ body: t ? JSON.stringify(t) : void 0
284
+ });
285
+ }
286
+ async delete(e, t) {
287
+ return this.request(e, {
288
+ ...t,
289
+ method: "DELETE"
290
+ });
291
+ }
292
+ }, N, P = (e) => {
293
+ N = new M(e);
294
+ }, F = "astrogators_ally_codes", I = "astrogators_selected_ally_code", L = () => {
295
+ try {
296
+ let e = localStorage.getItem(F);
297
+ return e ? JSON.parse(e) : [];
298
+ } catch (e) {
299
+ return console.error("Failed to read ally codes from localStorage:", e), [];
300
+ }
301
+ }, R = (e) => {
302
+ try {
303
+ let t = L();
304
+ if (t.some((t) => t.ally_code === e.ally_code)) return;
305
+ t.push(e), localStorage.setItem(F, JSON.stringify(t));
306
+ } catch (e) {
307
+ console.error("Failed to save ally code to localStorage:", e);
308
+ }
309
+ }, z = (e) => {
310
+ try {
311
+ let t = L().filter((t) => t.ally_code !== e);
312
+ localStorage.setItem(F, JSON.stringify(t));
313
+ } catch (e) {
314
+ console.error("Failed to remove ally code from localStorage:", e);
315
+ }
316
+ }, B = (e) => {
317
+ try {
318
+ let t = L().map((t) => t.ally_code === e ? {
319
+ ...t,
320
+ last_used_at: (/* @__PURE__ */ new Date()).toISOString()
321
+ } : t);
322
+ localStorage.setItem(F, JSON.stringify(t));
323
+ } catch (e) {
324
+ console.error("Failed to update ally code last used:", e);
325
+ }
326
+ }, V = () => localStorage.getItem(I), H = (e) => {
327
+ e ? localStorage.setItem(I, e) : localStorage.removeItem(I);
328
+ }, U = () => {
329
+ localStorage.removeItem(F), localStorage.removeItem(I);
330
+ }, W = t(void 0), G = ({ children: e, apiBaseUrl: t }) => {
331
+ let [r, o] = a(null), [c, l] = a(!0), [u, d] = a(!0), [f, p] = a(!0), [m, h] = a([]), [g, _] = a(null), [v, y] = a(!1), [b, x] = a({
332
+ show: !1,
333
+ localStorageCodes: []
334
+ });
335
+ i(() => {
336
+ P({ baseURL: t });
337
+ }, [t]), i(() => {
338
+ (async () => {
339
+ try {
340
+ d((await N.get("/api/v1/config/features")).auth_enabled);
341
+ } catch (e) {
342
+ console.error("Failed to fetch features:", e), d(!0);
343
+ } finally {
344
+ p(!1);
345
+ }
346
+ })();
347
+ }, [t]);
348
+ let S = n(async () => {
349
+ if (!j()) {
350
+ o(null), l(!1);
351
+ return;
352
+ }
353
+ try {
354
+ o(await N.get("/api/v1/users/me"));
355
+ } catch (e) {
356
+ console.error("Failed to fetch user:", e), o(null), A();
357
+ } finally {
358
+ l(!1);
359
+ }
360
+ }, []);
361
+ i(() => {
362
+ S();
363
+ }, [S]);
364
+ let C = async (e) => {
365
+ try {
366
+ let t = await N.post("/api/v1/auth/login", e);
367
+ k(t.access_token, t.refresh_token), o(await N.get("/api/v1/users/me"));
368
+ } catch (e) {
369
+ throw console.error("Login failed:", e), e;
370
+ }
371
+ }, w = async (e) => {
372
+ try {
373
+ await N.post("/api/v1/auth/register", e);
374
+ } catch (e) {
375
+ throw console.error("Registration failed:", e), e;
376
+ }
377
+ }, T = () => {
378
+ A(), o(null), h([]), _(null), x({
379
+ show: !1,
380
+ localStorageCodes: []
381
+ });
382
+ }, E = async () => {
383
+ await S();
384
+ }, D = async (e) => {
385
+ try {
386
+ return (await N.post("/api/v1/auth/forgot-password", e)).message;
387
+ } catch (e) {
388
+ throw console.error("Forgot password failed:", e), e;
389
+ }
390
+ }, O = async (e) => {
391
+ try {
392
+ return (await N.post("/api/v1/auth/reset-password", e)).message;
393
+ } catch (e) {
394
+ throw console.error("Reset password failed:", e), e;
395
+ }
396
+ }, M = async (e) => {
397
+ try {
398
+ return (await N.post("/api/v1/auth/resend-verification", e)).message;
399
+ } catch (e) {
400
+ throw console.error("Resend verification failed:", e), e;
401
+ }
402
+ }, F = n(async () => {
403
+ y(!0);
404
+ try {
405
+ if (r) {
406
+ h((await N.get("/api/v1/users/me/ally-codes")).ally_codes);
407
+ let e = L();
408
+ e.length > 0 && x({
409
+ show: !0,
410
+ localStorageCodes: e.map((e) => e.ally_code)
411
+ });
412
+ } else h(L());
413
+ _(V());
414
+ } catch (e) {
415
+ console.error("Failed to fetch ally codes:", e), h([]);
416
+ } finally {
417
+ y(!1);
418
+ }
419
+ }, [r]), I = n(async (e) => {
420
+ r && typeof e == "number" ? (await N.put(`/api/v1/users/me/ally-codes/${e}/use`, {}), await F()) : !r && typeof e == "string" && (B(e), h(L()));
421
+ }, [r, F]), G = n((e) => {
422
+ if (_(e), H(e), e && r) {
423
+ let t = m.find((t) => "ally_code" in t && t.ally_code === e);
424
+ t && "id" in t && I(t.id);
425
+ } else e && !r && B(e);
426
+ }, [
427
+ r,
428
+ m,
429
+ I
430
+ ]), K = n(async (e) => {
431
+ if (!/^\d{9}$/.test(e)) throw Error("Ally code must be exactly 9 digits");
432
+ if (r) {
433
+ let t = await N.post("/api/v1/users/me/ally-codes", { ally_code: e });
434
+ h((e) => [t, ...e]), m.length === 0 && G(e);
435
+ } else {
436
+ let t = await N.get(`/api/v1/player-data/player/${e}`);
437
+ if (!t) throw Error("Invalid ally code - player not found");
438
+ R({
439
+ ally_code: e,
440
+ player_name: t.data?.name ?? null,
441
+ last_used_at: (/* @__PURE__ */ new Date()).toISOString()
442
+ }), h(L()), m.length === 0 && G(e);
443
+ }
444
+ }, [
445
+ r,
446
+ m.length,
447
+ G
448
+ ]), q = n(async (e) => {
449
+ r && typeof e == "number" ? (await N.delete(`/api/v1/users/me/ally-codes/${e}`), h((t) => t.filter((t) => "id" in t && t.id !== e))) : !r && typeof e == "string" && (z(e), h(L()), g === e && G(null));
450
+ }, [
451
+ r,
452
+ g,
453
+ G
454
+ ]), J = n(() => {
455
+ x({
456
+ show: !1,
457
+ localStorageCodes: []
458
+ });
459
+ }, []), Y = n(async () => {
460
+ if (!r) return;
461
+ let e = L();
462
+ for (let t of e) try {
463
+ await K(t.ally_code);
464
+ } catch (e) {
465
+ console.error(`Failed to migrate ally code ${t.ally_code}:`, e);
466
+ }
467
+ U(), J();
468
+ }, [
469
+ r,
470
+ K,
471
+ J
472
+ ]);
473
+ i(() => {
474
+ F();
475
+ }, [F]);
476
+ let ee = {
477
+ user: r,
478
+ isAuthenticated: !!r,
479
+ isLoading: c,
480
+ login: C,
481
+ register: w,
482
+ logout: T,
483
+ refreshUser: E,
484
+ forgotPassword: D,
485
+ resetPassword: O,
486
+ resendVerification: M,
487
+ authEnabled: u,
488
+ isLoadingFeatures: f,
489
+ allyCodes: m,
490
+ selectedAllyCode: g,
491
+ isLoadingAllyCodes: v,
492
+ fetchAllyCodes: F,
493
+ addAllyCode: K,
494
+ removeAllyCode: q,
495
+ selectAllyCode: G,
496
+ updateAllyCodeLastUsed: I,
497
+ migrationPrompt: b,
498
+ dismissMigrationPrompt: J,
499
+ migrateLocalStorageCodes: Y
500
+ };
501
+ return /* @__PURE__ */ s(W.Provider, {
502
+ value: ee,
503
+ children: e
504
+ });
505
+ }, K = () => {
506
+ let e = r(W);
507
+ if (e === void 0) throw Error("useAuth must be used within an AuthProvider");
508
+ return e;
509
+ }, q = (e) => !e || e.length !== 9 ? e : `${e.slice(0, 3)}-${e.slice(3, 6)}-${e.slice(6, 9)}`, J = (e) => e.replace(/-/g, ""), Y = {
510
+ allyCodeDropdown: "_allyCodeDropdown_1m0tw_1",
511
+ select: "_select_1m0tw_8",
512
+ manageButton: "_manageButton_1m0tw_12",
513
+ managePanel: "_managePanel_1m0tw_16",
514
+ addSection: "_addSection_1m0tw_37",
515
+ addInputGroup: "_addInputGroup_1m0tw_43",
516
+ error: "_error_1m0tw_55",
517
+ success: "_success_1m0tw_61",
518
+ codesList: "_codesList_1m0tw_67",
519
+ codeItem: "_codeItem_1m0tw_71",
520
+ doneButton: "_doneButton_1m0tw_88"
521
+ }, ee = ({ onAllyCodeSelected: e, className: t = "" }) => {
522
+ let { allyCodes: n, selectedAllyCode: r, selectAllyCode: i, removeAllyCode: o, addAllyCode: l, isLoadingAllyCodes: u } = K(), [d, f] = a(!1), [p, m] = a(""), [h, _] = a(""), [y, x] = a(""), [S, C] = a(!1), w = n.map((e) => ({
523
+ value: e.ally_code,
524
+ label: e.player_name ? `${e.player_name} (${q(e.ally_code)})` : q(e.ally_code)
525
+ })), T = (t) => {
526
+ let n = t.target.value || null;
527
+ i(n), e?.(n);
528
+ }, E = async (e) => {
529
+ let t = n.find((t) => t.ally_code === e);
530
+ t && await o("id" in t ? t.id : t.ally_code);
531
+ };
532
+ return n.length === 0 ? null : /* @__PURE__ */ c("div", {
533
+ className: `${Y.allyCodeDropdown} ${t}`,
534
+ children: [
535
+ /* @__PURE__ */ s(b, {
536
+ options: w,
537
+ value: r || "",
538
+ onChange: T,
539
+ placeholder: "Select ally code",
540
+ disabled: u,
541
+ className: Y.select
542
+ }),
543
+ d && /* @__PURE__ */ c("div", {
544
+ className: Y.managePanel,
545
+ children: [
546
+ /* @__PURE__ */ s("h4", { children: "Manage Ally Codes" }),
547
+ /* @__PURE__ */ c("div", {
548
+ className: Y.addSection,
549
+ children: [
550
+ /* @__PURE__ */ c("div", {
551
+ className: Y.addInputGroup,
552
+ children: [/* @__PURE__ */ s(v, {
553
+ type: "text",
554
+ placeholder: "9-digit ally code",
555
+ value: p,
556
+ onChange: (e) => m(e.target.value.replace(/\D/g, "").slice(0, 9)),
557
+ disabled: S
558
+ }), /* @__PURE__ */ s(g, {
559
+ variant: "primary",
560
+ size: "sm",
561
+ onClick: async () => {
562
+ if (_(""), x(""), !/^\d{9}$/.test(p)) {
563
+ _("Ally code must be exactly 9 digits");
564
+ return;
565
+ }
566
+ C(!0);
567
+ try {
568
+ await l(p), x("Added successfully!"), m(""), setTimeout(() => x(""), 2e3);
569
+ } catch (e) {
570
+ _(e.message || "Failed to add ally code");
571
+ } finally {
572
+ C(!1);
573
+ }
574
+ },
575
+ loading: S,
576
+ disabled: p.length !== 9,
577
+ children: "Add"
578
+ })]
579
+ }),
580
+ h && /* @__PURE__ */ s("div", {
581
+ className: Y.error,
582
+ children: h
583
+ }),
584
+ y && /* @__PURE__ */ s("div", {
585
+ className: Y.success,
586
+ children: y
587
+ })
588
+ ]
589
+ }),
590
+ /* @__PURE__ */ s("div", {
591
+ className: Y.codesList,
592
+ children: n.map((e) => /* @__PURE__ */ c("div", {
593
+ className: Y.codeItem,
594
+ children: [/* @__PURE__ */ s("span", { children: e.player_name ? `${e.player_name} (${q(e.ally_code)})` : q(e.ally_code) }), /* @__PURE__ */ s(g, {
595
+ variant: "ghost",
596
+ size: "sm",
597
+ onClick: () => E(e.ally_code),
598
+ children: "Remove"
599
+ })]
600
+ }, e.ally_code))
601
+ }),
602
+ /* @__PURE__ */ s(g, {
603
+ variant: "secondary",
604
+ size: "sm",
605
+ onClick: () => f(!1),
606
+ className: Y.doneButton,
607
+ children: "Done"
608
+ })
609
+ ]
610
+ }),
611
+ /* @__PURE__ */ s(g, {
612
+ variant: "ghost",
613
+ size: "sm",
614
+ onClick: () => f(!d),
615
+ className: Y.manageButton,
616
+ children: "Manage"
617
+ })
618
+ ]
619
+ });
620
+ }, X = {
621
+ card: "_card_b4471_1",
622
+ chamfered: "_chamfered_b4471_8",
623
+ default: "_default_b4471_13",
624
+ elevated: "_elevated_b4471_17",
625
+ outline: "_outline_b4471_22",
626
+ "padding-none": "_padding-none_b4471_28",
627
+ "padding-sm": "_padding-sm_b4471_32",
628
+ "padding-md": "_padding-md_b4471_36",
629
+ "padding-lg": "_padding-lg_b4471_40",
630
+ hoverable: "_hoverable_b4471_45"
631
+ }, te = ({ children: e, variant: t = "default", chamfered: n = !1, chamferSize: r = "md", padding: i = "md", hoverable: a = !1, showDiagonalBorders: l = !1, diagonalBorderColor: u, className: d = "", onClick: f, style: p }) => {
632
+ let m = n ? r === "asymmetric" ? "chamfered-box-asymmetric" : r === "sm" ? "chamfered-box-sm" : r === "lg" ? "chamfered-box-lg" : "chamfered-box" : "", h = u ? { color: u } : void 0;
633
+ return /* @__PURE__ */ c("div", {
634
+ className: `${X.card} ${n ? X.chamfered : ""} ${X[t]} ${X[`padding-${i}`]} ${m} ${a ? X.hoverable : ""} ${d}`,
635
+ onClick: f,
636
+ role: f ? "button" : void 0,
637
+ tabIndex: f ? 0 : void 0,
638
+ style: p,
639
+ children: [l && /* @__PURE__ */ c(o, { children: [
640
+ /* @__PURE__ */ s("div", {
641
+ className: "chamfered-diagonal-border chamfered-diagonal-tl",
642
+ style: h
643
+ }),
644
+ /* @__PURE__ */ s("div", {
645
+ className: "chamfered-diagonal-border chamfered-diagonal-tr",
646
+ style: h
647
+ }),
648
+ /* @__PURE__ */ s("div", {
649
+ className: "chamfered-diagonal-border chamfered-diagonal-bl",
650
+ style: h
651
+ }),
652
+ /* @__PURE__ */ s("div", {
653
+ className: `chamfered-diagonal-border ${r === "asymmetric" ? "chamfered-diagonal-br-large" : "chamfered-diagonal-br"}`,
654
+ style: h
655
+ })
656
+ ] }), e]
657
+ });
658
+ }, Z = {
659
+ badge: "_badge_rk7t5_1",
660
+ sm: "_sm_rk7t5_11",
661
+ md: "_md_rk7t5_16",
662
+ lg: "_lg_rk7t5_21",
663
+ default: "_default_rk7t5_27",
664
+ primary: "_primary_rk7t5_32",
665
+ secondary: "_secondary_rk7t5_37",
666
+ success: "_success_rk7t5_42",
667
+ warning: "_warning_rk7t5_47",
668
+ error: "_error_rk7t5_52",
669
+ info: "_info_rk7t5_57"
670
+ }, ne = ({ children: e, variant: t = "default", size: n = "md", className: r = "" }) => /* @__PURE__ */ s("span", {
671
+ className: `${Z.badge} ${Z[t]} ${Z[n]} ${r}`,
672
+ children: e
673
+ }), Q = {
674
+ overlay: "_overlay_1b3yt_1",
675
+ fadeIn: "_fadeIn_1b3yt_1",
676
+ modal: "_modal_1b3yt_13",
677
+ slideUp: "_slideUp_1b3yt_1",
678
+ sm: "_sm_1b3yt_25",
679
+ md: "_md_1b3yt_30",
680
+ lg: "_lg_1b3yt_35",
681
+ xl: "_xl_1b3yt_40",
682
+ header: "_header_1b3yt_45",
683
+ title: "_title_1b3yt_53",
684
+ closeButton: "_closeButton_1b3yt_60",
685
+ content: "_content_1b3yt_78"
686
+ }, re = ({ isOpen: e, onClose: t, title: n, children: r, size: a = "md", closeOnOverlayClick: o = !0, className: l = "" }) => (i(() => (e ? document.body.style.overflow = "hidden" : document.body.style.overflow = "unset", () => {
687
+ document.body.style.overflow = "unset";
688
+ }), [e]), i(() => {
689
+ let n = (n) => {
690
+ n.key === "Escape" && e && t();
691
+ };
692
+ return document.addEventListener("keydown", n), () => document.removeEventListener("keydown", n);
693
+ }, [e, t]), e ? /* @__PURE__ */ s("div", {
694
+ className: Q.overlay,
695
+ onClick: (e) => {
696
+ o && e.target === e.currentTarget && t();
697
+ },
698
+ children: /* @__PURE__ */ c("div", {
699
+ className: `${Q.modal} ${Q[a]} ${l}`,
700
+ role: "dialog",
701
+ "aria-modal": "true",
702
+ children: [n && /* @__PURE__ */ c("div", {
703
+ className: Q.header,
704
+ children: [/* @__PURE__ */ s("h2", {
705
+ className: Q.title,
706
+ children: n
707
+ }), /* @__PURE__ */ s("button", {
708
+ className: Q.closeButton,
709
+ onClick: t,
710
+ "aria-label": "Close modal",
711
+ children: ""
712
+ })]
713
+ }), /* @__PURE__ */ s("div", {
714
+ className: Q.content,
715
+ children: r
716
+ })]
717
+ })
718
+ }) : null), $ = {
719
+ spinner: "_spinner_1uhnh_2",
720
+ spin: "_spin_1uhnh_2",
721
+ sm: "_sm_1uhnh_9",
722
+ md: "_md_1uhnh_15",
723
+ lg: "_lg_1uhnh_21",
724
+ dots: "_dots_1uhnh_34",
725
+ dot: "_dot_1uhnh_34",
726
+ bounce: "_bounce_1uhnh_1",
727
+ visuallyHidden: "_visuallyHidden_1uhnh_91"
728
+ }, ie = ({ size: e = "md", variant: t = "spinner", className: n = "" }) => t === "dots" ? /* @__PURE__ */ c("div", {
729
+ className: `${$.dots} ${$[e]} ${n}`,
730
+ children: [
731
+ /* @__PURE__ */ s("span", { className: $.dot }),
732
+ /* @__PURE__ */ s("span", { className: $.dot }),
733
+ /* @__PURE__ */ s("span", { className: $.dot })
734
+ ]
735
+ }) : /* @__PURE__ */ s("div", {
736
+ className: `${$.spinner} ${$[e]} ${n}`,
737
+ role: "status",
738
+ children: /* @__PURE__ */ s("span", {
739
+ className: $.visuallyHidden,
740
+ children: "Loading..."
741
+ })
742
+ });
743
+ //#endregion
744
+ export { ee as AllyCodeDropdown, M as ApiClient, G as AuthProvider, ne as Badge, g as Button, te as Card, u as Container, m as Footer, v as Input, ie as Loader, re as Modal, b as Select, f as TopBar, N as apiClient, U as clearAllyCodes, A as clearTokens, q as formatAllyCode, C as getAccessToken, L as getAllyCodesFromStorage, E as getRefreshToken, V as getSelectedAllyCode, P as initializeApiClient, j as isAuthenticated, T as removeAccessToken, z as removeAllyCodeFromStorage, O as removeRefreshToken, R as saveAllyCodeToStorage, w as setAccessToken, D as setRefreshToken, H as setSelectedAllyCode, k as setTokens, J as unformatAllyCode, B as updateAllyCodeLastUsed, K as useAuth };