@mundogamernetwork/shared-ui 1.1.80 → 1.1.82
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/components/keys/KeyCampaignDashboardCard.vue +2 -2
- package/locales/de.json +11 -1
- package/locales/en.json +11 -1
- package/locales/pt-BR.json +11 -1
- package/locales/ro.json +11 -1
- package/package.json +1 -1
- package/pages/key-campaigns/redeem-key-approved.vue +1 -1
- package/pages/key-campaigns/redeem-key.vue +176 -77
|
@@ -250,7 +250,7 @@ const detailRoute = computed(() =>
|
|
|
250
250
|
top: 6px;
|
|
251
251
|
right: 6px;
|
|
252
252
|
background: var(--primary);
|
|
253
|
-
color: #
|
|
253
|
+
color: var(--key-accent-ink, #13161C);
|
|
254
254
|
font-size: 11px;
|
|
255
255
|
font-weight: 700;
|
|
256
256
|
padding: 2px 7px;
|
|
@@ -280,7 +280,7 @@ const detailRoute = computed(() =>
|
|
|
280
280
|
bottom: 6px;
|
|
281
281
|
left: 6px;
|
|
282
282
|
background: var(--primary);
|
|
283
|
-
color: #
|
|
283
|
+
color: var(--key-accent-ink, #13161C);
|
|
284
284
|
font-size: 10px;
|
|
285
285
|
font-weight: 700;
|
|
286
286
|
padding: 3px 7px;
|
package/locales/de.json
CHANGED
|
@@ -174,7 +174,17 @@
|
|
|
174
174
|
"error_duplicate": "Sie haben bereits eine Anfrage für diese Kampagne. Überprüfen Sie 'Meine Bestellungen' für den Status.",
|
|
175
175
|
"error_user_blocked": "Ihr Zugang zu Key-Anfragen wurde vorübergehend gesperrt, da Material-Einreichungen überfällig sind. Bitte reichen Sie Ihre ausstehenden Materialien ein.",
|
|
176
176
|
"error_not_eligible": "Diese Kampagne ist für Ihren aktuellen Plan nicht verfügbar.",
|
|
177
|
-
"error_pending_limit": "Sie haben das gleichzeitige Anfragenlimit Ihres Plans erreicht. Bitte erfüllen Sie Ihre ausstehenden Verpflichtungen, bevor Sie einen neuen Key anfordern."
|
|
177
|
+
"error_pending_limit": "Sie haben das gleichzeitige Anfragenlimit Ihres Plans erreicht. Bitte erfüllen Sie Ihre ausstehenden Verpflichtungen, bevor Sie einen neuen Key anfordern.",
|
|
178
|
+
"select_option": "Option auswählen",
|
|
179
|
+
"required_data": "Erforderliche Angaben",
|
|
180
|
+
"already_requested": "Sie haben bereits eine Anfrage für diese Kampagne gestellt.",
|
|
181
|
+
"back_to_campaign": "Zur Kampagne zurückkehren",
|
|
182
|
+
"status_pending": "Anfrage ausstehend — bitte warten Sie auf die Genehmigung",
|
|
183
|
+
"status_approved": "Anfrage genehmigt — Sie können jetzt Ihren Schlüssel abrufen",
|
|
184
|
+
"status_completed": "Anfrage abgeschlossen",
|
|
185
|
+
"status_refused": "Anfrage abgelehnt",
|
|
186
|
+
"status_cancelled": "Anfrage storniert",
|
|
187
|
+
"refused_reason": "Grund der Ablehnung:"
|
|
178
188
|
},
|
|
179
189
|
"materials": {
|
|
180
190
|
"title": "Submit material",
|
package/locales/en.json
CHANGED
|
@@ -174,7 +174,17 @@
|
|
|
174
174
|
"error_duplicate": "You already have a request for this campaign. Check 'My Orders' to see the status.",
|
|
175
175
|
"error_user_blocked": "Your key request access has been temporarily blocked due to overdue material submissions. Please submit your pending materials to restore access.",
|
|
176
176
|
"error_not_eligible": "This campaign is not available for your current plan.",
|
|
177
|
-
"error_pending_limit": "You have reached the simultaneous request limit for your plan. Please fulfill your pending obligations before requesting a new key."
|
|
177
|
+
"error_pending_limit": "You have reached the simultaneous request limit for your plan. Please fulfill your pending obligations before requesting a new key.",
|
|
178
|
+
"select_option": "Select an option",
|
|
179
|
+
"required_data": "Required data",
|
|
180
|
+
"already_requested": "You have already submitted a request for this campaign.",
|
|
181
|
+
"back_to_campaign": "Back to campaign",
|
|
182
|
+
"status_pending": "Request pending — waiting for approval",
|
|
183
|
+
"status_approved": "Request approved — you can now retrieve your key",
|
|
184
|
+
"status_completed": "Request completed",
|
|
185
|
+
"status_refused": "Request refused",
|
|
186
|
+
"status_cancelled": "Request cancelled",
|
|
187
|
+
"refused_reason": "Reason for refusal:"
|
|
178
188
|
},
|
|
179
189
|
"materials": {
|
|
180
190
|
"title": "Submit material",
|
package/locales/pt-BR.json
CHANGED
|
@@ -174,7 +174,17 @@
|
|
|
174
174
|
"error_duplicate": "Você já tem um pedido para esta campanha. Acesse 'Meus Pedidos' para ver o status.",
|
|
175
175
|
"error_user_blocked": "Seu acesso a pedidos de chave está temporariamente bloqueado por materiais não entregues. Envie seus materiais pendentes para restaurar o acesso.",
|
|
176
176
|
"error_not_eligible": "Esta campanha não está disponível para o seu plano atual.",
|
|
177
|
-
"error_pending_limit": "Você atingiu o limite de pedidos simultâneos do seu plano. Entregue o material pendente antes de solicitar uma nova chave."
|
|
177
|
+
"error_pending_limit": "Você atingiu o limite de pedidos simultâneos do seu plano. Entregue o material pendente antes de solicitar uma nova chave.",
|
|
178
|
+
"select_option": "Selecione uma opção",
|
|
179
|
+
"required_data": "Dados obrigatórios",
|
|
180
|
+
"already_requested": "Você já enviou uma solicitação para esta campanha.",
|
|
181
|
+
"back_to_campaign": "Voltar para a campanha",
|
|
182
|
+
"status_pending": "Solicitação pendente — aguardando aprovação",
|
|
183
|
+
"status_approved": "Solicitação aprovada — você pode resgatar sua chave",
|
|
184
|
+
"status_completed": "Solicitação concluída",
|
|
185
|
+
"status_refused": "Solicitação recusada",
|
|
186
|
+
"status_cancelled": "Solicitação cancelada",
|
|
187
|
+
"refused_reason": "Motivo da recusa:"
|
|
178
188
|
},
|
|
179
189
|
"materials": {
|
|
180
190
|
"title": "Submit material",
|
package/locales/ro.json
CHANGED
|
@@ -174,7 +174,17 @@
|
|
|
174
174
|
"error_duplicate": "Aveți deja o cerere pentru această campanie. Verificați 'Comenzile mele' pentru status.",
|
|
175
175
|
"error_user_blocked": "Accesul dvs. la solicitările de chei a fost blocat temporar din cauza transmisiilor de materiale restante. Trimiteți materialele dvs. pentru a restabili accesul.",
|
|
176
176
|
"error_not_eligible": "Această campanie nu este disponibilă pentru planul dvs. actual.",
|
|
177
|
-
"error_pending_limit": "Ați atins limita de cereri simultane a planului dvs. Îndepliniți-vă obligațiile restante înainte de a solicita o nouă cheie."
|
|
177
|
+
"error_pending_limit": "Ați atins limita de cereri simultane a planului dvs. Îndepliniți-vă obligațiile restante înainte de a solicita o nouă cheie.",
|
|
178
|
+
"select_option": "Selectează o opțiune",
|
|
179
|
+
"required_data": "Date obligatorii",
|
|
180
|
+
"already_requested": "Ați trimis deja o cerere pentru această campanie.",
|
|
181
|
+
"back_to_campaign": "Înapoi la campanie",
|
|
182
|
+
"status_pending": "Cerere în așteptare — așteptați aprobarea",
|
|
183
|
+
"status_approved": "Cerere aprobată — puteți prelua cheia",
|
|
184
|
+
"status_completed": "Cerere finalizată",
|
|
185
|
+
"status_refused": "Cerere refuzată",
|
|
186
|
+
"status_cancelled": "Cerere anulată",
|
|
187
|
+
"refused_reason": "Motivul refuzului:"
|
|
178
188
|
},
|
|
179
189
|
"materials": {
|
|
180
190
|
"title": "Submit material",
|
package/package.json
CHANGED
|
@@ -302,7 +302,7 @@ function goBack() {
|
|
|
302
302
|
font-size: 14px;
|
|
303
303
|
font-weight: 700;
|
|
304
304
|
background: var(--key-accent, var(--primary, var(--key-accent, var(--primary, #D297FF))));
|
|
305
|
-
color: #
|
|
305
|
+
color: var(--key-accent-ink, #13161C);
|
|
306
306
|
border: none;
|
|
307
307
|
cursor: pointer;
|
|
308
308
|
transition: opacity 0.15s;
|
|
@@ -75,6 +75,33 @@ const canSubmit = computed(() =>
|
|
|
75
75
|
!!selectedPlatformId.value && !!selectedRegionId.value && !!quantity.value && !submitting.value,
|
|
76
76
|
)
|
|
77
77
|
|
|
78
|
+
// Collapsible "Required data" box — matches tv's original toggle behavior
|
|
79
|
+
const isBoxOpen = ref(true)
|
|
80
|
+
function toggleBox() {
|
|
81
|
+
isBoxOpen.value = !isBoxOpen.value
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// request_status: null/undefined/1 = no request yet, anything else = existing request
|
|
85
|
+
const hasExistingRequest = computed(() => {
|
|
86
|
+
const s = campaign.value?.request_status
|
|
87
|
+
return s !== null && s !== undefined && s !== 1
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
const existingRequestStatus = computed(() => {
|
|
91
|
+
switch (campaign.value?.request_status) {
|
|
92
|
+
case 2: return $i18n.t("keys.campaigns.status_pending")
|
|
93
|
+
case 3: return $i18n.t("keys.campaigns.status_approved")
|
|
94
|
+
case 4: return $i18n.t("keys.campaigns.status_approved")
|
|
95
|
+
case 5: return $i18n.t("keys.campaigns.status_completed")
|
|
96
|
+
case 6: return $i18n.t("keys.campaigns.status_refused")
|
|
97
|
+
case 7: return $i18n.t("keys.campaigns.status_cancelled")
|
|
98
|
+
default: return ""
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
const isRefused = computed(() => campaign.value?.request_status === 6)
|
|
103
|
+
const refusedReason = computed(() => campaign.value?.request_admin_notes || "")
|
|
104
|
+
|
|
78
105
|
async function submit() {
|
|
79
106
|
if (!canSubmit.value) return
|
|
80
107
|
submitting.value = true
|
|
@@ -147,63 +174,74 @@ function goBack() {
|
|
|
147
174
|
<p v-if="campaign?.name" class="campaign-name">{{ campaign.name }}</p>
|
|
148
175
|
</div>
|
|
149
176
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
<
|
|
153
|
-
|
|
154
|
-
<div class="
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
class="option"
|
|
160
|
-
:class="{ selected: selectedPlatformId === p.id }"
|
|
161
|
-
@click="selectedPlatformId = p.id"
|
|
162
|
-
>
|
|
163
|
-
{{ p.name }}
|
|
164
|
-
</button>
|
|
177
|
+
<!-- Already has a request -->
|
|
178
|
+
<div v-if="hasExistingRequest" class="existing-request-notice">
|
|
179
|
+
<MGIcon size="1x" icon="version" class="notice-icon" />
|
|
180
|
+
<div class="notice-texts">
|
|
181
|
+
<div class="notice-title">{{ $t("keys.campaigns.already_requested") }}</div>
|
|
182
|
+
<div class="notice-status">{{ existingRequestStatus }}</div>
|
|
183
|
+
<div v-if="isRefused && refusedReason" class="notice-reason">
|
|
184
|
+
<span class="notice-reason-label">{{ $t("keys.campaigns.refused_reason") }}</span>
|
|
185
|
+
<span class="notice-reason-text">{{ refusedReason }}</span>
|
|
165
186
|
</div>
|
|
166
187
|
</div>
|
|
188
|
+
<button class="btn notice-back" @click="goBack">
|
|
189
|
+
{{ $t("keys.campaigns.back_to_campaign") }}
|
|
190
|
+
</button>
|
|
191
|
+
</div>
|
|
167
192
|
|
|
168
|
-
|
|
169
|
-
<div class="
|
|
170
|
-
<
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
class="
|
|
177
|
-
:class="{ selected: selectedRegionId === r.id }"
|
|
178
|
-
@click="selectedRegionId = r.id"
|
|
179
|
-
>
|
|
180
|
-
{{ r.name }}
|
|
193
|
+
<form v-else class="form" @submit.prevent="submit">
|
|
194
|
+
<div class="required-data">
|
|
195
|
+
<div class="required-data-header" @click="toggleBox">
|
|
196
|
+
<div class="required-data-header-left">
|
|
197
|
+
<MGIcon size="1x" icon="check" :style="{ color: isBoxOpen ? 'var(--key-accent, var(--primary, #D297FF))' : 'var(--inactive)' }" />
|
|
198
|
+
<span>{{ $t("keys.campaigns.required_data") }}</span>
|
|
199
|
+
</div>
|
|
200
|
+
<button type="button" class="box-toggler" :aria-expanded="isBoxOpen">
|
|
201
|
+
<MGIcon icon="chevron-down" :class="{ rotate: isBoxOpen }" />
|
|
181
202
|
</button>
|
|
182
203
|
</div>
|
|
183
|
-
</div>
|
|
184
204
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
v-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
205
|
+
<div v-show="isBoxOpen" class="required-data-body">
|
|
206
|
+
<div class="form-row">
|
|
207
|
+
<label class="label">{{ $t("keys.campaigns.platform") }}</label>
|
|
208
|
+
<select v-model.number="selectedPlatformId" class="select">
|
|
209
|
+
<option :value="null" disabled>{{ $t("keys.campaigns.select_option") }}</option>
|
|
210
|
+
<option v-for="p in platforms" :key="p.id" :value="p.id">{{ p.name }}</option>
|
|
211
|
+
</select>
|
|
212
|
+
</div>
|
|
213
|
+
|
|
214
|
+
<div class="form-row">
|
|
215
|
+
<label class="label">{{ $t("keys.campaigns.region") }}</label>
|
|
216
|
+
<select v-model.number="selectedRegionId" class="select">
|
|
217
|
+
<option :value="null" disabled>{{ $t("keys.campaigns.select_option") }}</option>
|
|
218
|
+
<option v-for="r in regions" :key="r.id" :value="r.id">{{ r.name || r.localized_name }}</option>
|
|
219
|
+
</select>
|
|
220
|
+
</div>
|
|
221
|
+
|
|
222
|
+
<div class="form-row" v-if="maxKeysForUser > 1">
|
|
223
|
+
<label class="label">{{ $t("keys.campaigns.quantity") }}</label>
|
|
224
|
+
<input
|
|
225
|
+
v-model.number="quantity"
|
|
226
|
+
type="number"
|
|
227
|
+
min="1"
|
|
228
|
+
:max="maxKeysForUser"
|
|
229
|
+
class="input quantity-input"
|
|
230
|
+
:placeholder="$t('keys.campaigns.quantity')"
|
|
231
|
+
@change="clampQuantity"
|
|
232
|
+
/>
|
|
233
|
+
</div>
|
|
234
|
+
|
|
235
|
+
<div class="form-row">
|
|
236
|
+
<label class="label">{{ $t("keys.campaigns.description_optional") }}</label>
|
|
237
|
+
<textarea
|
|
238
|
+
v-model="description"
|
|
239
|
+
class="textarea"
|
|
240
|
+
:placeholder="$t('keys.campaigns.description_placeholder')"
|
|
241
|
+
rows="3"
|
|
242
|
+
/>
|
|
243
|
+
</div>
|
|
244
|
+
</div>
|
|
207
245
|
</div>
|
|
208
246
|
|
|
209
247
|
<div v-if="requestError" class="req-error">{{ requestError }}</div>
|
|
@@ -276,59 +314,120 @@ function goBack() {
|
|
|
276
314
|
|
|
277
315
|
.form { display: flex; flex-direction: column; gap: 24px; }
|
|
278
316
|
|
|
279
|
-
.
|
|
317
|
+
.required-data {
|
|
280
318
|
display: flex;
|
|
281
319
|
flex-direction: column;
|
|
282
|
-
|
|
320
|
+
background: var(--bg-app-badge);
|
|
321
|
+
border: 1px solid var(--button-secondary-default-bg);
|
|
283
322
|
}
|
|
284
323
|
|
|
285
|
-
.
|
|
286
|
-
|
|
324
|
+
.required-data-header {
|
|
325
|
+
display: flex;
|
|
326
|
+
align-items: center;
|
|
327
|
+
justify-content: space-between;
|
|
328
|
+
gap: 10px;
|
|
329
|
+
padding: 16px 20px;
|
|
330
|
+
font-size: 14px;
|
|
287
331
|
font-weight: 600;
|
|
288
332
|
color: var(--card-article-title);
|
|
333
|
+
border-bottom: 1px solid var(--button-secondary-default-bg);
|
|
334
|
+
cursor: pointer;
|
|
289
335
|
}
|
|
290
336
|
|
|
291
|
-
.
|
|
337
|
+
.required-data-header-left {
|
|
292
338
|
display: flex;
|
|
293
|
-
|
|
294
|
-
gap:
|
|
339
|
+
align-items: center;
|
|
340
|
+
gap: 10px;
|
|
295
341
|
}
|
|
296
342
|
|
|
297
|
-
.
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
font-weight: 500;
|
|
301
|
-
border: 1px solid var(--button-secondary-default-bg);
|
|
343
|
+
.box-toggler {
|
|
344
|
+
display: flex;
|
|
345
|
+
align-items: center;
|
|
302
346
|
background: transparent;
|
|
347
|
+
border: none;
|
|
303
348
|
color: var(--secondary-info-fg);
|
|
304
349
|
cursor: pointer;
|
|
305
|
-
transition: border-color 0.15s, color 0.15s;
|
|
306
350
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
border-color: var(--key-accent, var(--primary, var(--key-accent, var(--primary, #D297FF))));
|
|
310
|
-
color: var(--key-accent, var(--primary, var(--key-accent, var(--primary, #D297FF))));
|
|
311
|
-
background: var(--key-accent-subtle-bg, rgba(210, 151, 255, 0.08));
|
|
312
|
-
}
|
|
351
|
+
svg { transition: transform 0.15s; }
|
|
352
|
+
svg.rotate { transform: rotate(180deg); }
|
|
313
353
|
}
|
|
314
354
|
|
|
315
|
-
.
|
|
316
|
-
|
|
355
|
+
.existing-request-notice {
|
|
356
|
+
display: flex;
|
|
357
|
+
align-items: flex-start;
|
|
358
|
+
gap: 14px;
|
|
359
|
+
padding: 20px;
|
|
360
|
+
background: var(--bg-app-badge);
|
|
361
|
+
border: 1px solid var(--button-secondary-default-bg);
|
|
317
362
|
}
|
|
318
363
|
|
|
319
|
-
.
|
|
320
|
-
|
|
321
|
-
|
|
364
|
+
.notice-icon { color: var(--key-accent, var(--primary, #D297FF)); margin-top: 2px; }
|
|
365
|
+
|
|
366
|
+
.notice-texts { flex: 1; display: flex; flex-direction: column; gap: 4px; }
|
|
367
|
+
|
|
368
|
+
.notice-title { font-size: 14px; font-weight: 600; color: var(--card-article-title); }
|
|
369
|
+
.notice-status { font-size: 13px; color: var(--secondary-info-fg); }
|
|
370
|
+
|
|
371
|
+
.notice-reason {
|
|
372
|
+
display: flex;
|
|
373
|
+
flex-direction: column;
|
|
374
|
+
gap: 2px;
|
|
375
|
+
margin-top: 6px;
|
|
376
|
+
font-size: 13px;
|
|
377
|
+
|
|
378
|
+
.notice-reason-label { font-weight: 600; color: var(--card-article-title); }
|
|
379
|
+
.notice-reason-text { color: var(--secondary-info-fg); }
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
.notice-back {
|
|
383
|
+
background: transparent;
|
|
322
384
|
border: 1px solid var(--button-secondary-default-bg);
|
|
323
385
|
color: var(--card-article-title);
|
|
386
|
+
padding: 8px 16px;
|
|
387
|
+
font-size: 13px;
|
|
388
|
+
font-weight: 600;
|
|
389
|
+
cursor: pointer;
|
|
390
|
+
white-space: nowrap;
|
|
391
|
+
&:hover { border-color: var(--key-accent, var(--primary, #D297FF)); }
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
.form-row {
|
|
395
|
+
display: flex;
|
|
396
|
+
flex-direction: column;
|
|
397
|
+
gap: 10px;
|
|
398
|
+
padding: 20px;
|
|
399
|
+
& + .form-row { border-top: 1px solid var(--button-secondary-default-bg); }
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
.label {
|
|
403
|
+
font-size: 13px;
|
|
404
|
+
font-weight: 600;
|
|
405
|
+
color: var(--card-article-title);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
.select, .input, .textarea {
|
|
409
|
+
width: 100%;
|
|
410
|
+
background-color: transparent;
|
|
411
|
+
border: 1px solid rgba(128, 128, 128, 0.46);
|
|
412
|
+
color: var(--secondary-info-fg);
|
|
324
413
|
font-size: 13px;
|
|
325
414
|
padding: 10px 12px;
|
|
326
|
-
resize: vertical;
|
|
327
415
|
outline: none;
|
|
328
416
|
font-family: inherit;
|
|
329
417
|
&:focus { border-color: var(--key-accent, var(--primary, var(--key-accent, var(--primary, #D297FF)))); }
|
|
330
418
|
}
|
|
331
419
|
|
|
420
|
+
.select {
|
|
421
|
+
appearance: auto;
|
|
422
|
+
cursor: pointer;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
.textarea { resize: vertical; }
|
|
426
|
+
|
|
427
|
+
.quantity-input {
|
|
428
|
+
width: 120px;
|
|
429
|
+
}
|
|
430
|
+
|
|
332
431
|
.req-error {
|
|
333
432
|
font-size: 13px;
|
|
334
433
|
color: var(--danger, #e53935);
|
|
@@ -341,7 +440,7 @@ function goBack() {
|
|
|
341
440
|
font-size: 14px;
|
|
342
441
|
font-weight: 700;
|
|
343
442
|
background: var(--key-accent, var(--primary, var(--key-accent, var(--primary, #D297FF))));
|
|
344
|
-
color: #
|
|
443
|
+
color: var(--key-accent-ink, #13161C);
|
|
345
444
|
border: none;
|
|
346
445
|
cursor: pointer;
|
|
347
446
|
transition: opacity 0.15s;
|