@mundogamernetwork/shared-ui 1.17.0 → 1.17.4

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.
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { ref, watch, onMounted } from "vue";
2
+ import { computed, ref, watch, onMounted } from "vue";
3
3
  import type { AxiosInstance } from "axios";
4
4
  import { useMgBillingProfile } from "../../composables/useMgBillingProfile";
5
5
 
@@ -15,11 +15,14 @@ const props = defineProps<{
15
15
  httpService: AxiosInstance;
16
16
  /** Start expanded regardless of whether a profile already exists. */
17
17
  defaultOpen?: boolean;
18
+ /** Override the endpoint when the instance's baseURL is an unusual shape. */
19
+ path?: string;
18
20
  }>();
19
21
 
20
22
  const emit = defineEmits<{ (e: "change", wanted: boolean): void }>();
21
23
 
22
- const billing = useMgBillingProfile(props.httpService);
24
+ const nuxtApp = typeof useNuxtApp === "function" ? useNuxtApp() : null;
25
+ const billing = useMgBillingProfile(props.httpService, { path: props.path });
23
26
  const wanted = ref(props.defaultOpen ?? false);
24
27
 
25
28
  // A customer who already gave us their details should see them, ticked — not
@@ -47,6 +50,16 @@ async function save(): Promise<boolean> {
47
50
  return billing.save();
48
51
  }
49
52
 
53
+ const saveFailed = computed(() => billing.error.value !== null);
54
+
55
+ const saveErrorMessage = computed(() => {
56
+ if (billing.error.value) return billing.error.value;
57
+ const translated = (nuxtApp?.$i18n as any)?.t?.("billing_profile.save_error");
58
+ return translated && translated !== "billing_profile.save_error"
59
+ ? translated
60
+ : "Could not save your billing details. Please try again.";
61
+ });
62
+
50
63
  defineExpose({ save, wanted, profile: billing.profile, hasData: billing.hasData });
51
64
  </script>
52
65
 
@@ -103,18 +116,28 @@ defineExpose({ save, wanted, profile: billing.profile, hasData: billing.hasData
103
116
  </label>
104
117
  </div>
105
118
 
106
- <p v-if="billing.error.value" class="mg-billing-profile__error">
107
- {{ billing.error.value || $t?.("billing_profile.save_error") ?? "Could not save your billing details. Please try again." }}
119
+ <p v-if="saveFailed" class="mg-billing-profile__error">
120
+ {{ saveErrorMessage }}
108
121
  </p>
109
122
  </div>
110
123
  </div>
111
124
  </template>
112
125
 
113
126
  <style lang="scss" scoped>
127
+ /*
128
+ * Theme-agnostic on purpose. This block renders inside eight different
129
+ * checkouts, and they are not all light: agency's is near-black, and hardcoded
130
+ * light fallbacks turned the labels dark-on-dark and the inputs into glaring
131
+ * white boxes. Everything here inherits the host's own text colour and derives
132
+ * its lines from it, so the block reads correctly on any background without
133
+ * each app having to restyle it.
134
+ */
114
135
  .mg-billing-profile {
115
136
  margin-top: 16px;
116
- border-top: 1px solid var(--inactive, #ececec);
137
+ border-top: 1px solid currentColor;
138
+ border-top-color: color-mix(in srgb, currentColor 18%, transparent);
117
139
  padding-top: 16px;
140
+ color: inherit;
118
141
  }
119
142
 
120
143
  .mg-billing-profile__toggle {
@@ -123,6 +146,7 @@ defineExpose({ save, wanted, profile: billing.profile, hasData: billing.hasData
123
146
  gap: 8px;
124
147
  font-size: 14px;
125
148
  cursor: pointer;
149
+ color: inherit;
126
150
  }
127
151
 
128
152
  .mg-billing-profile__body {
@@ -131,8 +155,8 @@ defineExpose({ save, wanted, profile: billing.profile, hasData: billing.hasData
131
155
 
132
156
  .mg-billing-profile__hint {
133
157
  font-size: 13px;
134
- color: var(--inactive-text, #666);
135
158
  margin: 0 0 12px;
159
+ opacity: 0.7;
136
160
  }
137
161
 
138
162
  .mg-billing-profile__grid {
@@ -148,16 +172,28 @@ defineExpose({ save, wanted, profile: billing.profile, hasData: billing.hasData
148
172
  font-size: 12px;
149
173
  }
150
174
 
175
+ .mg-billing-profile__field > span {
176
+ opacity: 0.7;
177
+ }
178
+
151
179
  .mg-billing-profile__field--wide {
152
180
  grid-column: 1 / -1;
153
181
  }
154
182
 
155
183
  .mg-billing-profile__field input {
156
- border: 1px solid var(--inactive, #d5d5d5);
184
+ border: 1px solid currentColor;
185
+ border-color: color-mix(in srgb, currentColor 30%, transparent);
157
186
  padding: 8px 10px;
158
187
  font-size: 14px;
159
- background: var(--bg, #fff);
160
- color: var(--active, #111);
188
+ /* Transparent, not white: the host's own background shows through, so the
189
+ field belongs to the surrounding form instead of punching a hole in it. */
190
+ background: transparent;
191
+ color: inherit;
192
+ }
193
+
194
+ .mg-billing-profile__field input:focus {
195
+ outline: none;
196
+ border-color: color-mix(in srgb, currentColor 60%, transparent);
161
197
  }
162
198
 
163
199
  .mg-billing-profile__error {
@@ -12,7 +12,25 @@ import type { AxiosInstance } from "axios";
12
12
  * the payment record is created on the way back from the gateway, so anything
13
13
  * asked for afterwards misses at least the first document.
14
14
  */
15
- const BILLING_PROFILE_URL = "api/v1/public/user/billing-profile";
15
+ const BILLING_PROFILE_PATH = "public/user/billing-profile";
16
+
17
+ /**
18
+ * Resolve the endpoint for whichever axios instance the app hands us.
19
+ *
20
+ * Instances across the platform disagree about their baseURL: useMgCheckout's
21
+ * is origin-only (so it writes "api/v1/shopping-cart"), while most apps'
22
+ * api-main instance already ends in "/api/v1". Hardcoding either shape would
23
+ * force a wrapper service in every app that happens to use the other one.
24
+ */
25
+ function resolveBillingProfileUrl(httpService: AxiosInstance, override?: string): string {
26
+ if (override) return override;
27
+
28
+ const baseUrl = String(httpService?.defaults?.baseURL ?? "");
29
+
30
+ return /\/api\/v1\/?$/.test(baseUrl)
31
+ ? BILLING_PROFILE_PATH
32
+ : `api/v1/${BILLING_PROFILE_PATH}`;
33
+ }
16
34
 
17
35
  export interface MgBillingProfile {
18
36
  name: string;
@@ -48,7 +66,9 @@ export function emptyMgBillingProfile(): MgBillingProfile {
48
66
  };
49
67
  }
50
68
 
51
- export function useMgBillingProfile(httpService: AxiosInstance) {
69
+ export function useMgBillingProfile(httpService: AxiosInstance, options?: { path?: string }) {
70
+ const url = resolveBillingProfileUrl(httpService, options?.path);
71
+
52
72
  const profile = ref<MgBillingProfile>(emptyMgBillingProfile());
53
73
  const loading = ref(false);
54
74
  const saving = ref(false);
@@ -62,7 +82,7 @@ export function useMgBillingProfile(httpService: AxiosInstance) {
62
82
  async function load() {
63
83
  loading.value = true;
64
84
  try {
65
- const res = await httpService.get(BILLING_PROFILE_URL);
85
+ const res = await httpService.get(url);
66
86
  const data = res?.data?.data ?? {};
67
87
  (Object.keys(profile.value) as Array<keyof MgBillingProfile>).forEach((key) => {
68
88
  profile.value[key] = data[key] ?? "";
@@ -85,7 +105,7 @@ export function useMgBillingProfile(httpService: AxiosInstance) {
85
105
  saving.value = true;
86
106
  error.value = null;
87
107
  try {
88
- await httpService.put(BILLING_PROFILE_URL, profile.value);
108
+ await httpService.put(url, profile.value);
89
109
  return true;
90
110
  } catch (err: any) {
91
111
  error.value = err?.response?.data?.message ?? null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mundogamernetwork/shared-ui",
3
- "version": "1.17.0",
3
+ "version": "1.17.4",
4
4
  "description": "Mundo Gamer Network - Shared UI Layer (Nuxt 3)",
5
5
  "type": "module",
6
6
  "main": "./nuxt.config.ts",
@@ -473,7 +473,7 @@ export const fetchCampaignTypes = (params: Record<string, any> = {}) => {
473
473
  * Fetch active platforms (for the platform filter select).
474
474
  */
475
475
  export const fetchCampaignPlatforms = () => {
476
- return authClient.get("/public/key-platforms")
476
+ return authClient.get("/platforms/currently")
477
477
  }
478
478
 
479
479
  /**