@mundogamernetwork/shared-ui 1.1.0 → 1.1.2

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.
@@ -0,0 +1,136 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * MgLoginRegisterMenu — standardized guest dropdown for the header user icon.
4
+ *
5
+ * Shows a prominent Login button + "Don't have an account yet? Register" link,
6
+ * fully themed via platform CSS variables (academy orange, tv cyan, etc.).
7
+ *
8
+ * Redirect rules are baked in and correct for every platform:
9
+ * - Login → the platform's own login endpoint (apiBaseURL host) with
10
+ * redirect_to = current page, so the user RETURNS here after login.
11
+ * - Register → accountsBaseUrl/register with redirect_to + system_id.
12
+ *
13
+ * Usage (header guest state): place inside a `position: relative` parent
14
+ * <li class="menu-item" style="position: relative">
15
+ * <MgLoginRegisterMenu v-if="!signedIn && open" />
16
+ * </li>
17
+ *
18
+ * Props let a platform override the login base or disable dropdown positioning.
19
+ */
20
+ import { buildLoginUrl, buildRegisterUrl } from "../../utils/authRedirect";
21
+
22
+ const props = defineProps({
23
+ // Override the login URL entirely (else derived from apiBaseURL host).
24
+ loginUrl: { type: String, default: "" },
25
+ // When false, renders as an inline card instead of an absolute dropdown.
26
+ dropdown: { type: Boolean, default: true },
27
+ });
28
+
29
+ const runtimeConfig = useRuntimeConfig();
30
+
31
+ const apiBase = (
32
+ (runtimeConfig.public.mgSharedUi?.apiBaseURL as string) ||
33
+ (runtimeConfig.public.apiBaseURL as string) ||
34
+ (import.meta.env.VITE_API_BASE_URL as string) ||
35
+ ""
36
+ ).replace(/\/api\/v1\/?$/, "");
37
+
38
+ const accountsBaseUrl =
39
+ runtimeConfig.public.mgSharedUi?.accountsBaseUrl ||
40
+ runtimeConfig.public.accountsBaseUrl ||
41
+ import.meta.env.VITE_BASE_ACCOUNTS_URL ||
42
+ "";
43
+
44
+ const systemId =
45
+ runtimeConfig.public.mgSharedUi?.systemId ||
46
+ runtimeConfig.public.platformId ||
47
+ import.meta.env.VITE_SYSTEM_ID ||
48
+ "";
49
+
50
+ // Computed at click time so redirect_to is always the CURRENT url.
51
+ function goLogin() {
52
+ if (typeof window === "undefined") return;
53
+ window.location.href = props.loginUrl || buildLoginUrl(apiBase);
54
+ }
55
+ function goRegister() {
56
+ if (typeof window === "undefined") return;
57
+ window.location.href = buildRegisterUrl(accountsBaseUrl, undefined, systemId);
58
+ }
59
+ </script>
60
+
61
+ <template>
62
+ <div class="mg-login-register" :class="{ 'mg-login-register--dropdown': dropdown }">
63
+ <button type="button" class="mg-login-register__login" @click="goLogin">
64
+ {{ $t("header.login.btn_login") }}
65
+ </button>
66
+ <p class="mg-login-register__register">
67
+ {{ $t("header.login.no_account") }}
68
+ <a class="mg-login-register__register-link" @click.prevent="goRegister">
69
+ {{ $t("header.login.btn_register") }}
70
+ </a>
71
+ </p>
72
+ </div>
73
+ </template>
74
+
75
+ <style scoped lang="scss">
76
+ .mg-login-register {
77
+ display: flex;
78
+ flex-direction: column;
79
+ gap: 0.85rem;
80
+ padding: 1.25rem;
81
+ // Inline (default): fill the parent dropdown container.
82
+ width: 100%;
83
+ box-sizing: border-box;
84
+ background: var(--header-ui-config-bg, var(--sidebar-bg, var(--body-bg-card, #1c1c1c)));
85
+
86
+ // Dropdown variant: self-positioned card with its own width + border.
87
+ &--dropdown {
88
+ position: absolute;
89
+ top: 100%;
90
+ right: 0;
91
+ margin-top: 8px;
92
+ z-index: 9999;
93
+ width: 300px;
94
+ max-width: 300px;
95
+ border: 1px solid var(--header-ui-config-border, var(--border-card, rgba(255, 255, 255, 0.08)));
96
+ }
97
+
98
+ &__login {
99
+ display: flex;
100
+ align-items: center;
101
+ justify-content: center;
102
+ width: 100%;
103
+ min-height: 44px;
104
+ padding: 10px 16px;
105
+ font-size: 15px;
106
+ font-weight: 600;
107
+ border: none;
108
+ cursor: pointer;
109
+ white-space: nowrap;
110
+ text-decoration: none;
111
+ // Platform theme highlight + readable contrast text.
112
+ background: var(--bt-active, var(--header-active-fg, var(--highlight-color, #f70)));
113
+ color: var(--header-active-bg, #18181a);
114
+ transition: opacity 0.15s;
115
+
116
+ &:hover { opacity: 0.9; }
117
+ }
118
+
119
+ &__register {
120
+ margin: 0;
121
+ text-align: center;
122
+ font-size: 13px;
123
+ color: var(--sidebar-menus-fg, var(--inactive, #aaa));
124
+ }
125
+
126
+ &__register-link {
127
+ color: var(--bt-active, var(--header-active-fg, var(--highlight-color, #f70)));
128
+ font-weight: 600;
129
+ text-decoration: none;
130
+ cursor: pointer;
131
+ margin-left: 4px;
132
+
133
+ &:hover { text-decoration: underline; }
134
+ }
135
+ }
136
+ </style>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mundogamernetwork/shared-ui",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "Mundo Gamer Network - Shared UI Layer (Nuxt 3)",
5
5
  "type": "module",
6
6
  "main": "./nuxt.config.ts",
@@ -39,4 +39,4 @@
39
39
  "nuxt": "^3.15.4",
40
40
  "typescript": "^5.0.0"
41
41
  }
42
- }
42
+ }
@@ -54,10 +54,11 @@ export function getHttpService(): AxiosInstance {
54
54
  recoverFromSessionLoss();
55
55
  }
56
56
 
57
- // 5xx while a credentialed request is in flight is the classic
58
- // stale-oauth_token loop (OAuth rejects 500). Clear client-side so
59
- // the next load is a clean guest instead of an infinite failure.
60
- if (status >= 500) {
57
+ // 5xx ONLY on the auth probe = the stale-oauth_token loop (the session
58
+ // check itself fails). A 5xx from any OTHER endpoint (notifications,
59
+ // feed, etc.) is just a broken/erroring endpoint it must NOT clear
60
+ // the session, otherwise a single backend 500 logs the user out.
61
+ if (status >= 500 && isAuthProbe) {
61
62
  recoverFromSessionLoss();
62
63
  }
63
64