@mundogamernetwork/shared-ui 1.0.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.
Files changed (87) hide show
  1. package/README.md +283 -0
  2. package/components/PressKit/AssetGallery.vue +349 -0
  3. package/components/PressKit/Awards.vue +100 -0
  4. package/components/PressKit/Credits.vue +78 -0
  5. package/components/PressKit/FactSheet.vue +204 -0
  6. package/components/PressKit/Hero.vue +143 -0
  7. package/components/PressKit/Quotes.vue +80 -0
  8. package/components/PressKit/VideoPlayer.vue +134 -0
  9. package/components/checkout/MgCartItemList.vue +214 -0
  10. package/components/checkout/MgCartSummary.vue +204 -0
  11. package/components/checkout/MgCheckoutSidebar.vue +230 -0
  12. package/components/checkout/MgGuestEmailForm.vue +97 -0
  13. package/components/checkout/MgPaymentMethodSelector.vue +162 -0
  14. package/components/checkout/MgPixQRCode.vue +222 -0
  15. package/components/indie-wall/IndieWallLeaderboard.vue +208 -0
  16. package/components/indie-wall/MuralCanvas.vue +481 -0
  17. package/components/indie-wall/StepBlock.vue +314 -0
  18. package/components/indie-wall/StepCustomize.vue +530 -0
  19. package/components/indie-wall/StepGoal.vue +169 -0
  20. package/components/indie-wall/StepPackage.vue +145 -0
  21. package/components/indie-wall/StepPay.vue +209 -0
  22. package/components/indie-wall/SupportStepper.vue +372 -0
  23. package/components/invoices/MgInvoiceDownload.vue +50 -0
  24. package/components/pricing/MgBillingToggle.vue +74 -0
  25. package/components/pricing/MgPricingCard.vue +245 -0
  26. package/components/ui/Header/MgMessageCard.vue +147 -0
  27. package/components/ui/Header/MgMessageModal.vue +414 -0
  28. package/components/ui/Header/MgNotificationCard.vue +200 -0
  29. package/components/ui/Header/MgNotificationsModal.vue +125 -0
  30. package/components/ui/MgAnnouncementBanner.vue +147 -0
  31. package/components/ui/MgBanners.vue +23 -0
  32. package/components/ui/MgHeaderComponent.vue +283 -0
  33. package/components/ui/MgHeaderUIConfig.vue +225 -0
  34. package/components/ui/MgHeaderUIUser.vue +301 -0
  35. package/components/ui/MgLoginModal.vue +156 -0
  36. package/components/ui/MgPromotionBanner.vue +185 -0
  37. package/composables/useLogout.ts +42 -0
  38. package/composables/useMgCheckout.ts +287 -0
  39. package/composables/useMgUserNotifications.ts +122 -0
  40. package/composables/usePaymentMethods.ts +75 -0
  41. package/composables/useSubscription.ts +163 -0
  42. package/middleware/auth.global.ts +40 -0
  43. package/nuxt.config.ts +31 -0
  44. package/package.json +40 -0
  45. package/pages/[slug]/index.vue +112 -0
  46. package/pages/about.vue +133 -0
  47. package/pages/blog.vue +430 -0
  48. package/pages/careers.vue +329 -0
  49. package/pages/contact.vue +339 -0
  50. package/pages/faq.vue +317 -0
  51. package/pages/health-check.vue +20 -0
  52. package/pages/icons.vue +58 -0
  53. package/pages/magazine/[slug].vue +209 -0
  54. package/pages/magazine/index.vue +267 -0
  55. package/pages/media-kit/[slug].vue +625 -0
  56. package/pages/mural/[slug].vue +1058 -0
  57. package/pages/partners.vue +290 -0
  58. package/pages/press.vue +237 -0
  59. package/pages/presskit/[slug].vue +191 -0
  60. package/pages/roadmap.vue +355 -0
  61. package/pages/status.vue +199 -0
  62. package/pages/team.vue +266 -0
  63. package/pages/wall/[slug].vue +11 -0
  64. package/plugins/auth.client.ts +17 -0
  65. package/plugins/echo.client.ts +132 -0
  66. package/services/authService.ts +95 -0
  67. package/services/chatService.ts +53 -0
  68. package/services/contactService.ts +35 -0
  69. package/services/documentService.ts +16 -0
  70. package/services/httpService.ts +95 -0
  71. package/services/indieWallService.ts +174 -0
  72. package/services/institutionalService.ts +248 -0
  73. package/services/mediaKitService.ts +51 -0
  74. package/services/notificationsService.ts +20 -0
  75. package/services/pressKitService.ts +55 -0
  76. package/stores/announcement.ts +129 -0
  77. package/stores/auth.ts +86 -0
  78. package/stores/chat.ts +150 -0
  79. package/stores/contact.ts +28 -0
  80. package/stores/document.ts +27 -0
  81. package/stores/index.ts +34 -0
  82. package/stores/institutional.ts +231 -0
  83. package/stores/login.ts +27 -0
  84. package/stores/notifications.ts +133 -0
  85. package/stores/promotion.ts +154 -0
  86. package/types/index.ts +135 -0
  87. package/utils/serialize.ts +29 -0
package/pages/team.vue ADDED
@@ -0,0 +1,266 @@
1
+ <script setup lang="ts">
2
+ import { storeToRefs } from "pinia";
3
+
4
+ definePageMeta({ layout: "default" });
5
+
6
+ const institutionalStore = useInstitutionalStore();
7
+ const { team, operationalArea } = storeToRefs(institutionalStore);
8
+
9
+ const selectedArea = ref<string | number>("");
10
+
11
+ async function fetchTeamData() {
12
+ try {
13
+ const params: any = {
14
+ filter: { status: 1 },
15
+ sort: "name",
16
+ order: "asc",
17
+ per_page: "all",
18
+ };
19
+ if (selectedArea.value) params.filter.operational_area_id = selectedArea.value;
20
+ await institutionalStore.fetchTeam(params);
21
+ } catch {
22
+ // silent
23
+ }
24
+ }
25
+
26
+ async function fetchAreas() {
27
+ try {
28
+ await institutionalStore.fetchOperationalArea({ per_page: "all" });
29
+ } catch {
30
+ // silent
31
+ }
32
+ }
33
+
34
+ function selectArea(areaId: string | number) {
35
+ selectedArea.value = selectedArea.value === areaId ? "" : areaId;
36
+ fetchTeamData();
37
+ }
38
+
39
+ onMounted(async () => {
40
+ fetchTeamData();
41
+ fetchAreas();
42
+ });
43
+ </script>
44
+
45
+ <template>
46
+ <div id="team" class="container team">
47
+ <section>
48
+ <div class="header">
49
+ <div>
50
+ <h1 class="title-4">{{ $t("more.team.title") }}</h1>
51
+ <p>{{ $t("more.team.subtitle") }}</p>
52
+ </div>
53
+ </div>
54
+ <div class="container">
55
+ <div class="row">
56
+ <div class="col-8 offset-2">
57
+ <div class="area-tabs" v-if="operationalArea?.data?.data">
58
+ <button
59
+ class="area-tab"
60
+ :class="{ active: selectedArea === '' }"
61
+ @click="selectArea('')"
62
+ >
63
+ {{ $t("more.team.all") }}
64
+ </button>
65
+ <button
66
+ v-for="area in operationalArea.data.data"
67
+ :key="area.id"
68
+ class="area-tab"
69
+ :class="{ active: selectedArea === area.id }"
70
+ @click="selectArea(area.id)"
71
+ >
72
+ {{ area.localized_name || area.name }}
73
+ </button>
74
+ </div>
75
+
76
+ <div v-if="team.status === 'pending'" class="loading">
77
+ <p>{{ $t("components.loading") }}</p>
78
+ </div>
79
+
80
+ <div v-else-if="team?.data?.data && team.data.data.length > 0" class="team-grid">
81
+ <div
82
+ v-for="member in team.data.data"
83
+ :key="member.id"
84
+ class="team-card"
85
+ >
86
+ <img
87
+ :src="member.avatar_url || '/imgs/default.jpg'"
88
+ :alt="member.name"
89
+ class="team-card__avatar"
90
+ />
91
+ <div class="team-card__info">
92
+ <h3>{{ member.name }}</h3>
93
+ <p class="role">{{ member.role || member.operational_area?.name }}</p>
94
+ <p class="description" v-if="member.localized_description">
95
+ {{ member.localized_description }}
96
+ </p>
97
+ <div class="team-card__countries" v-if="member.countries?.length">
98
+ <img
99
+ v-for="c in member.countries"
100
+ :key="c.id"
101
+ :src="c.flag_svg_src || c.flag_32_url"
102
+ :alt="c.name"
103
+ class="flag"
104
+ />
105
+ </div>
106
+ <div class="team-card__social" v-if="member.social_links?.length">
107
+ <a
108
+ v-for="link in member.social_links"
109
+ :key="link.url"
110
+ :href="link.url"
111
+ target="_blank"
112
+ rel="noopener"
113
+ >
114
+ <MGIcon :icon="link.platform || 'link'" />
115
+ </a>
116
+ </div>
117
+ </div>
118
+ </div>
119
+ </div>
120
+
121
+ <div v-else class="no-data">
122
+ {{ $t("more.team.no_data") }}
123
+ </div>
124
+ </div>
125
+ </div>
126
+ </div>
127
+ </section>
128
+ </div>
129
+ </template>
130
+
131
+ <style lang="scss" scoped>
132
+ .team {
133
+ color: var(--inactive);
134
+ font-size: 0.875rem;
135
+
136
+ .header {
137
+ position: relative;
138
+ height: 200px;
139
+ display: flex;
140
+ justify-content: center;
141
+ align-items: center;
142
+ margin-bottom: 2rem;
143
+
144
+ & > div {
145
+ width: 480px;
146
+ text-align: center;
147
+ }
148
+
149
+ &:before {
150
+ content: " ";
151
+ display: block;
152
+ position: absolute;
153
+ background: url("@/assets/images/bg-team.png") no-repeat center center / cover;
154
+ width: 100%;
155
+ height: 100%;
156
+ top: 50%;
157
+ transform: translateY(-50%);
158
+ z-index: -1;
159
+ }
160
+ }
161
+
162
+ .area-tabs {
163
+ display: flex;
164
+ flex-wrap: wrap;
165
+ gap: 8px;
166
+ margin-bottom: 24px;
167
+
168
+ .area-tab {
169
+ padding: 6px 16px;
170
+ border: 1px solid var(--search-bar-border-color);
171
+ background: transparent;
172
+ color: var(--inactive);
173
+ font-size: 14px;
174
+ cursor: pointer;
175
+ transition: all 0.2s;
176
+
177
+ &.active {
178
+ background: var(--chip-text);
179
+ color: var(--chip-background-2);
180
+ border-color: var(--chip-text);
181
+ }
182
+ }
183
+ }
184
+
185
+ .team-grid {
186
+ display: grid;
187
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
188
+ gap: 24px;
189
+ }
190
+
191
+ .team-card {
192
+ background-color: var(--chip-background-2);
193
+ text-align: center;
194
+ padding: 16px;
195
+
196
+ &__avatar {
197
+ width: 96px;
198
+ height: 96px;
199
+ border-radius: 50%;
200
+ object-fit: cover;
201
+ margin-bottom: 12px;
202
+ }
203
+
204
+ &__info {
205
+ h3 {
206
+ font-size: 14px;
207
+ font-weight: 600;
208
+ color: var(--card-cover-title);
209
+ margin-bottom: 4px;
210
+ }
211
+
212
+ .role {
213
+ font-size: 12px;
214
+ color: var(--chip-text);
215
+ margin-bottom: 8px;
216
+ }
217
+
218
+ .description {
219
+ font-size: 12px;
220
+ line-height: 16px;
221
+ margin-bottom: 8px;
222
+ }
223
+ }
224
+
225
+ &__countries {
226
+ display: flex;
227
+ justify-content: center;
228
+ gap: 4px;
229
+ margin-bottom: 8px;
230
+
231
+ .flag {
232
+ width: 20px;
233
+ height: 14px;
234
+ object-fit: cover;
235
+ }
236
+ }
237
+
238
+ &__social {
239
+ display: flex;
240
+ justify-content: center;
241
+ gap: 8px;
242
+
243
+ a {
244
+ color: var(--inactive);
245
+ font-size: 16px;
246
+
247
+ &:hover {
248
+ color: var(--chip-text);
249
+ }
250
+ }
251
+ }
252
+ }
253
+
254
+ .no-data {
255
+ text-align: center;
256
+ padding: 32px;
257
+ color: var(--secondary-info-fg);
258
+ }
259
+ }
260
+
261
+ @media screen and (max-width: 768px) {
262
+ .team .team-grid {
263
+ grid-template-columns: repeat(2, 1fr);
264
+ }
265
+ }
266
+ </style>
@@ -0,0 +1,11 @@
1
+ <script setup lang="ts">
2
+ const route = useRoute()
3
+ const localePath = useLocalePath()
4
+ const slug = route.params.slug as string
5
+ const qs = Object.keys(route.query).length
6
+ ? '?' + new URLSearchParams(route.query as Record<string, string>).toString()
7
+ : ''
8
+ navigateTo(localePath(`/mural/${slug}`) + qs, { replace: true })
9
+ </script>
10
+
11
+ <template><div /></template>
@@ -0,0 +1,17 @@
1
+ export default defineNuxtPlugin({
2
+ name: "shared-ui-auth",
3
+ enforce: "pre",
4
+ parallel: true,
5
+ async setup() {
6
+ try {
7
+ const authStore = useAuthStore();
8
+
9
+ if (!authStore.signedIn) {
10
+ await authStore.getUser();
11
+ }
12
+ } catch (e) {
13
+ // Auth store may not be available in all extending frontends
14
+ console.warn("[shared-ui Auth] Failed to initialize auth:", e);
15
+ }
16
+ },
17
+ });
@@ -0,0 +1,132 @@
1
+ import Echo from "laravel-echo";
2
+ import Pusher from "pusher-js";
3
+ import axios from "axios";
4
+
5
+ declare global {
6
+ interface Window {
7
+ Pusher: any;
8
+ Echo: any;
9
+ }
10
+ }
11
+
12
+ export default defineNuxtPlugin({
13
+ name: "shared-ui-echo",
14
+ enforce: "post",
15
+ parallel: true,
16
+ setup(nuxtApp) {
17
+ // Skip if already provided by the extending frontend's own Echo plugin
18
+ if (nuxtApp.$echo || window.Echo) {
19
+ return;
20
+ }
21
+
22
+ const pusherKey = import.meta.env.VITE_MIX_PUSHER_APP_KEY;
23
+ const pusherHost = import.meta.env.VITE_MIX_PUSHER_HOST;
24
+
25
+ // Skip if credentials are not configured
26
+ if (!pusherKey || !pusherHost) {
27
+ console.warn("[shared-ui Echo] Pusher credentials not configured, skipping");
28
+ return;
29
+ }
30
+
31
+ const headers: Record<string, string> = {
32
+ Accept: "application/json",
33
+ };
34
+
35
+ if (import.meta.env.VITE_BEARER_TOKEN) {
36
+ headers.Authorization = `Bearer ${import.meta.env.VITE_BEARER_TOKEN}`;
37
+ }
38
+
39
+ window.Pusher = Pusher;
40
+ window.Echo = new Echo({
41
+ broadcaster: "pusher",
42
+ key: import.meta.env.VITE_MIX_PUSHER_APP_KEY,
43
+ cluster: import.meta.env.VITE_MIX_PUSHER_APP_CLUSTER ?? "mt1",
44
+ wsHost: import.meta.env.VITE_MIX_PUSHER_HOST,
45
+ wsPort: import.meta.env.VITE_MIX_PUSHER_PORT ?? 80,
46
+ wssPort: import.meta.env.VITE_MIX_PUSHER_PORT ?? 443,
47
+ forceTLS: (import.meta.env.VITE_MIX_PUSHER_SCHEME ?? "https") === "https",
48
+ enabledTransports: ["ws", "wss"],
49
+ disableStats: true,
50
+ enableLogging: import.meta.env.VITE_APP_ENV !== "production",
51
+ activityTimeout: 30000,
52
+ pongTimeout: 5000,
53
+ authorizer: (channel: any) => {
54
+ return {
55
+ authorize: (socketId: any, callback: any) => {
56
+ axios
57
+ .post(
58
+ import.meta.env.VITE_PUSHER_AUTH,
59
+ {
60
+ socket_id: socketId,
61
+ channel_name: channel.name,
62
+ },
63
+ {
64
+ withCredentials: true,
65
+ headers: headers,
66
+ },
67
+ )
68
+ .then((response) => {
69
+ callback(false, response.data);
70
+ })
71
+ .catch((error) => {
72
+ callback(true, error);
73
+ });
74
+ },
75
+ };
76
+ },
77
+ });
78
+
79
+ window.Echo.connector.pusher.connection.bind("connected", () => {
80
+ console.log("[WebSocket] Connected", new Date().toISOString());
81
+ });
82
+
83
+ window.Echo.connector.pusher.connection.bind("disconnected", () => {
84
+ console.log("[WebSocket] Disconnected", new Date().toISOString());
85
+ });
86
+
87
+ window.Echo.connector.pusher.connection.bind("error", (error: any) => {
88
+ console.error("[WebSocket] Connection error:", error, new Date().toISOString());
89
+ });
90
+
91
+ let reconnectTimer: number | null = null;
92
+ let reconnectAttempts = 0;
93
+ const MAX_RECONNECT_ATTEMPTS = 5;
94
+
95
+ window.Echo.connector.pusher.connection.bind("state_change", (states: any) => {
96
+ const { previous, current } = states;
97
+ console.log(`[WebSocket] State changed: ${previous} -> ${current}`);
98
+
99
+ if (current === "disconnected" || current === "failed" || current === "unavailable") {
100
+ // Stop reconnecting after max attempts to avoid infinite loop
101
+ // (e.g. when user is not authenticated)
102
+ if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
103
+ console.log("[WebSocket] Max reconnect attempts reached, stopping.");
104
+ if (reconnectTimer) {
105
+ clearTimeout(reconnectTimer);
106
+ reconnectTimer = null;
107
+ }
108
+ return;
109
+ }
110
+
111
+ reconnectAttempts++;
112
+ const delay = Math.min(1000 * Math.pow(2, reconnectAttempts - 1), 30000);
113
+ console.log(`[WebSocket] Reconnecting in ${delay / 1000}s (attempt ${reconnectAttempts}/${MAX_RECONNECT_ATTEMPTS})...`);
114
+
115
+ if (reconnectTimer) clearTimeout(reconnectTimer);
116
+ reconnectTimer = window.setTimeout(() => {
117
+ window.Echo.connector.pusher.connect();
118
+ }, delay);
119
+ }
120
+
121
+ if (current === "connected") {
122
+ reconnectAttempts = 0;
123
+ if (reconnectTimer) {
124
+ clearTimeout(reconnectTimer);
125
+ reconnectTimer = null;
126
+ }
127
+ }
128
+ });
129
+
130
+ nuxtApp.provide("echo", window.Echo);
131
+ },
132
+ });
@@ -0,0 +1,95 @@
1
+ import httpService from "./httpService";
2
+ import type { MgUser } from "../types";
3
+
4
+ export class User implements Partial<MgUser> {
5
+ id = null;
6
+ uuid = null;
7
+ name = null;
8
+ nickname = null;
9
+ avatar = null;
10
+ avatar_url = null;
11
+ inviteQrCode = null;
12
+ followHash = null;
13
+ follow_hash = null;
14
+ followers = null;
15
+ following = null;
16
+ followers_count = null;
17
+ following_count = null;
18
+ user_is_following = false;
19
+ coins = null;
20
+ bio = { short: "", long: "" };
21
+ short_bio = "";
22
+ long_bio = "";
23
+ country = {
24
+ id: null,
25
+ name: null,
26
+ localized_name: null,
27
+ originalName: null,
28
+ language_id: null,
29
+ languageId: null,
30
+ isocode: null,
31
+ code2: null,
32
+ code3: null,
33
+ flag: null,
34
+ flag_url: null,
35
+ };
36
+ invite_qr_code = null;
37
+
38
+ constructor(data: object) {
39
+ Object.assign(this, data);
40
+ return this;
41
+ }
42
+ }
43
+
44
+ export const logout = () =>
45
+ httpService({
46
+ url: "logout",
47
+ method: "POST",
48
+ });
49
+
50
+ const instance = new (class AuthService {
51
+ private user: User | null = null;
52
+
53
+ authenticate(options: { fresh?: boolean } = {}): Promise<User | null> {
54
+ return new Promise((resolve, reject) => {
55
+ const params: Record<string, any> = {};
56
+ // Tells the API to bust its cache before computing subscription
57
+ // details — used right after a payment confirmation so the new
58
+ // is_subscriber state propagates without a stale TTL.
59
+ if (options.fresh) params.fresh = 1;
60
+ const xhr = httpService.get("/auth/user", { params });
61
+ xhr.then((response: any) => {
62
+ if (response.status !== 200 || !response.data || response.data === "") {
63
+ resolve(null);
64
+ return;
65
+ }
66
+ const user = new User(response.data);
67
+ Object.freeze(user);
68
+ this.user = user;
69
+ resolve(user);
70
+ }).catch((error: any) => {
71
+ const status = error?.response?.status;
72
+ if (status === 401 || status === 403 || status === 419) {
73
+ resolve(null);
74
+ return;
75
+ }
76
+ reject(error);
77
+ });
78
+ });
79
+ }
80
+
81
+ async getUser(options: { fresh?: boolean } = {}) {
82
+ const user = await this.authenticate(options);
83
+ if (user) return user;
84
+ return null;
85
+ }
86
+
87
+ async logout() {
88
+ return httpService({
89
+ url: "logout",
90
+ method: "POST",
91
+ });
92
+ }
93
+ })();
94
+
95
+ export default instance;
@@ -0,0 +1,53 @@
1
+ import httpService from "./httpService";
2
+ import { serialize } from "../utils/serialize";
3
+
4
+ function getEndpoints() {
5
+ const config = useRuntimeConfig();
6
+ return (
7
+ config.public.mgSharedUi?.chatEndpoints ?? {
8
+ list: "/api/v1/chats",
9
+ send: "/api/v1/chats/messages/",
10
+ show: "/api/v1/chats/{chatId}",
11
+ unread: "api/v1/chats/messages/unread/count",
12
+ delete: "/api/v1/chats/{chatId}",
13
+ deleteMessage: "/api/v1/chats/messages/{messageId}",
14
+ }
15
+ );
16
+ }
17
+
18
+ export const getChatList = async (params: any) => {
19
+ const endpoints = getEndpoints();
20
+ const paramsSerialized: string = serialize(params);
21
+ return httpService.get(`${endpoints.list}${paramsSerialized}`);
22
+ };
23
+
24
+ export const postChatMessage = async (params: any) => {
25
+ const endpoints = getEndpoints();
26
+ return httpService.post(endpoints.send, params);
27
+ };
28
+
29
+ export const getChat = async (params: { chat_id: string | number }) => {
30
+ const endpoints = getEndpoints();
31
+ const url = endpoints.show.replace("{chatId}", String(params.chat_id));
32
+ return httpService.get(url);
33
+ };
34
+
35
+ export const getUnreadMessagesCount = async () => {
36
+ const config = useRuntimeConfig();
37
+ const endpoints = getEndpoints();
38
+ const systemId = config.public.mgSharedUi?.systemId || import.meta.env.VITE_SYSTEM_ID;
39
+ const param = { mg_network_system_id: systemId };
40
+ return httpService.get(`${endpoints.unread}${serialize(param)}`);
41
+ };
42
+
43
+ export const deleteUserChat = async (chatId: string | number) => {
44
+ const endpoints = getEndpoints();
45
+ const url = endpoints.delete.replace("{chatId}", String(chatId));
46
+ return httpService.delete(url);
47
+ };
48
+
49
+ export const deleteChatMessage = async (chatMessageId: string | number) => {
50
+ const endpoints = getEndpoints();
51
+ const url = endpoints.deleteMessage.replace("{messageId}", String(chatMessageId));
52
+ return httpService.delete(url);
53
+ };
@@ -0,0 +1,35 @@
1
+ import httpService from "./httpService";
2
+ import { serialize } from "../utils/serialize";
3
+
4
+ interface SerializeObject {
5
+ [key: string]: string | { [key: string]: string | string[] };
6
+ }
7
+
8
+ const getApiBaseUrl = () => {
9
+ const config = useRuntimeConfig();
10
+ return config.public.mgSharedUi?.apiBaseURL || import.meta.env.VITE_API_BASE_URL;
11
+ };
12
+
13
+ export const fetchContactCountry = async (params: SerializeObject): Promise<any> => {
14
+ const paramsSerialized = serialize(params);
15
+ return httpService.get(`/countries${paramsSerialized}`, { baseURL: getApiBaseUrl() });
16
+ };
17
+
18
+ export const fetchSubject = async (params: SerializeObject): Promise<any> => {
19
+ const paramsSerialized = serialize(params);
20
+ return httpService.get(`/contact-subjects${paramsSerialized}`, { baseURL: getApiBaseUrl() });
21
+ };
22
+
23
+ export const createMessage = async (data: {
24
+ name: string;
25
+ email: string;
26
+ subject_id: number;
27
+ language_slug: string;
28
+ country_id: number;
29
+ message: string;
30
+ privacy_policy: number;
31
+ origin_network_id: number;
32
+ status?: number;
33
+ }): Promise<any> => {
34
+ return httpService.post(`/contact`, data, { baseURL: getApiBaseUrl() });
35
+ };
@@ -0,0 +1,16 @@
1
+ import httpService from "./httpService";
2
+ import { serialize } from "../utils/serialize";
3
+
4
+ interface SerializeObject {
5
+ [key: string]: string | { [key: string]: string | string[] };
6
+ }
7
+
8
+ const getApiBaseUrl = () => {
9
+ const config = useRuntimeConfig();
10
+ return config.public.mgSharedUi?.apiBaseURL || import.meta.env.VITE_API_BASE_URL;
11
+ };
12
+
13
+ export const fetchDocuments = async (params: SerializeObject): Promise<any> => {
14
+ const paramsSerialized = serialize(params);
15
+ return httpService.get(`/document-website-latest${paramsSerialized}`, { baseURL: getApiBaseUrl() });
16
+ };