mirror of
https://github.com/PhaseII-eAmusement-Network/PhaseWeb3-Vue.git
synced 2026-04-25 07:18:31 -05:00
Move arcade api calls to dedicated file, save arcade settings.
Some checks failed
Build / build (push) Has been cancelled
Some checks failed
Build / build (push) Has been cancelled
This commit is contained in:
parent
f351d291ac
commit
5e00903ef9
|
|
@ -50,10 +50,11 @@
|
|||
<div id="particles-js"></div>
|
||||
<script src="/assets/particles.js"></script>
|
||||
|
||||
<script src="/assets/snow.js"></script>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
|
||||
<script src="/assets/snow.js"></script>
|
||||
|
||||
|
||||
<!-- Bats! -->
|
||||
<!-- <script src="https://code.jquery.com/jquery.js"></script>
|
||||
|
|
|
|||
60
src/constants/values.js
Normal file
60
src/constants/values.js
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
export function getNestedValue(obj, path) {
|
||||
return path.split(".").reduce((acc, part) => acc && acc[part], obj);
|
||||
}
|
||||
|
||||
export function setNestedValue(obj, path, value) {
|
||||
const keys = path.split(".");
|
||||
const lastKey = keys.pop();
|
||||
const nestedObj = keys.reduce((acc, key) => (acc[key] = acc[key] || {}), obj);
|
||||
nestedObj[lastKey] = value;
|
||||
}
|
||||
|
||||
export function transformNonUnicode(value, maxLength) {
|
||||
const allowedCharsRegex = /^[0-9A-Z!?#$&*-. ]*$/;
|
||||
const transformedValue = value.toUpperCase().slice(0, maxLength);
|
||||
|
||||
return (
|
||||
allowedCharsRegex.test(transformedValue) ? transformedValue : ""
|
||||
).toUpperCase();
|
||||
}
|
||||
|
||||
export function transformUnicode(value, maxLength) {
|
||||
let transformedValue = "";
|
||||
|
||||
for (
|
||||
let i = 0;
|
||||
i < value.length && transformedValue.length < maxLength;
|
||||
i++
|
||||
) {
|
||||
let c = value.charCodeAt(i);
|
||||
if (c >= 0x30 && c <= 0x39) {
|
||||
// '0' to '9'
|
||||
c = 0xff10 + (c - 0x30);
|
||||
} else if (c >= 0x41 && c <= 0x5a) {
|
||||
// 'A' to 'Z'
|
||||
c = 0xff21 + (c - 0x41);
|
||||
} else if (c >= 0x61 && c <= 0x7a) {
|
||||
// 'a' to 'z'
|
||||
c = 0xff41 + (c - 0x61);
|
||||
} else if (c === 0x40) {
|
||||
// '@'
|
||||
c = 0xff20;
|
||||
} else if (c === 0x2c) {
|
||||
// ','
|
||||
c = 0xff0c;
|
||||
} else if (c === 0x2e) {
|
||||
// '.'
|
||||
c = 0xff0e;
|
||||
} else if (c === 0x5f) {
|
||||
// '_'
|
||||
c = 0xff3f;
|
||||
}
|
||||
transformedValue += String.fromCharCode(c);
|
||||
}
|
||||
|
||||
const allowedCharsRegex =
|
||||
/^[\uFF20-\uFF3A\uFF41-\uFF5A\uFF10-\uFF19\uFF0C\uFF0E\uFF3F\u3041-\u308D\u308F\u3092\u3093\u30A1-\u30ED\u30EF\u30F2\u30F3\u30FC]*$/;
|
||||
return (
|
||||
allowedCharsRegex.test(transformedValue) ? transformedValue : ""
|
||||
).toUpperCase();
|
||||
}
|
||||
|
|
@ -45,6 +45,7 @@ img {
|
|||
}
|
||||
|
||||
#particles-js {
|
||||
height: full;
|
||||
min-width: screen;
|
||||
min-height: screen;
|
||||
position: absolute;
|
||||
}
|
||||
|
|
@ -10,3 +10,37 @@ export async function APIGetArcade(arcadeId) {
|
|||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function APIGetArcadeVPN(arcadeId) {
|
||||
try {
|
||||
const data = await mainStore.callApi(`/arcade/${arcadeId}/exportVPN`);
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.log("Error fetching arcade VPN:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function APIUpdateArcade(arcadeId, newArcade) {
|
||||
try {
|
||||
const data = await mainStore.callApi(
|
||||
`/arcade/${arcadeId}`,
|
||||
"POST",
|
||||
newArcade
|
||||
);
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.log("Error updating arcade:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function APIGetArcadePASELI(arcadeId) {
|
||||
try {
|
||||
const data = await mainStore.callApi(`/arcade/${arcadeId}/paseli`);
|
||||
return data.data;
|
||||
} catch (error) {
|
||||
console.log("Error fetching arcade PASELI data:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -266,36 +266,6 @@ export const useMainStore = defineStore("main", {
|
|||
}
|
||||
},
|
||||
|
||||
async getArcade(arcadeId) {
|
||||
try {
|
||||
const data = await this.callApi(`/arcade/${arcadeId}`);
|
||||
return data.arcade;
|
||||
} catch (error) {
|
||||
console.log("Error fetching arcade:", error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
async getArcadeVPN(arcadeId) {
|
||||
try {
|
||||
const data = await this.callApi(`/arcade/${arcadeId}/exportVPN`);
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.log("Error fetching arcade VPN:", error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
async getPaseliData(arcadeId) {
|
||||
try {
|
||||
const data = await this.callApi(`/arcade/${arcadeId}/paseli`);
|
||||
return data.data;
|
||||
} catch (error) {
|
||||
console.log("Error fetching PASELI:", error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
async getMusicData(game, version, songIds = null, oneChart = false) {
|
||||
try {
|
||||
const data = await this.callApi(
|
||||
|
|
|
|||
|
|
@ -1,37 +1,88 @@
|
|||
<script setup>
|
||||
import { useRoute } from "vue-router";
|
||||
import { ref, onMounted } from "vue";
|
||||
import { mdiStore, mdiCogOutline } from "@mdi/js";
|
||||
import { mdiStore, mdiStoreCog, mdiCogOutline } from "@mdi/js";
|
||||
import SectionMain from "@/components/SectionMain.vue";
|
||||
import LayoutAuthenticated from "@/layouts/LayoutAuthenticated.vue";
|
||||
import SectionTitleLine from "@/components/SectionTitleLine.vue";
|
||||
import ArcadeCard from "@/components/ArcadeCard.vue";
|
||||
import CardBox from "@/components/CardBox.vue";
|
||||
import FormField from "@/components/FormField.vue";
|
||||
// import FormFilePicker from "@/components/FormFilePicker.vue";
|
||||
import FormCheckRadio from "@/components/FormCheckRadio.vue";
|
||||
// import FormControl from "@/components/FormControl.vue";
|
||||
import PillTag from "@/components/PillTag.vue";
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
// import CardBoxWidget from "@/components/CardBoxWidget.vue";
|
||||
// import { listCodes } from "@/constants/area";
|
||||
import CardBoxWidget from "@/components/CardBoxWidget.vue";
|
||||
import { getNestedValue, setNestedValue } from "@/constants/values";
|
||||
import {
|
||||
APIGetArcade,
|
||||
APIUpdateArcade,
|
||||
APIGetArcadeVPN,
|
||||
} from "@/stores/api/arcade";
|
||||
|
||||
import { useMainStore } from "@/stores/main";
|
||||
const mainStore = useMainStore();
|
||||
const arcadeData = ref({});
|
||||
const optionForm = ref(null);
|
||||
const bareForm = ref(null);
|
||||
const arcadeData = ref(null);
|
||||
const loading = ref(true);
|
||||
|
||||
const $route = useRoute();
|
||||
const arcadeId = parseInt($route.params.id);
|
||||
|
||||
onMounted(async () => {
|
||||
var arcadeOptions = [
|
||||
{
|
||||
id: "paseli_enabled",
|
||||
name: "PASELI Services",
|
||||
help: "Enable PASELI for this arcade.",
|
||||
type: "Boolean",
|
||||
},
|
||||
{
|
||||
id: "paseli_infinite",
|
||||
name: "Infinite PASELI",
|
||||
help: "Enable infinite PASELI for this arcade.",
|
||||
type: "Boolean",
|
||||
},
|
||||
{
|
||||
id: "maint",
|
||||
name: "Maintenance Mode",
|
||||
help: "Place this arcade under maintenance.",
|
||||
type: "Boolean",
|
||||
},
|
||||
{
|
||||
id: "hide_network",
|
||||
name: "Incognito Mode",
|
||||
help: "Hide the network and all ranking data.",
|
||||
type: "Boolean",
|
||||
},
|
||||
];
|
||||
|
||||
async function loadArcade() {
|
||||
try {
|
||||
const data = await mainStore.getArcade(arcadeId);
|
||||
arcadeData.value = {};
|
||||
optionForm.value = {};
|
||||
bareForm.value = {};
|
||||
const data = await APIGetArcade(arcadeId);
|
||||
arcadeData.value = data;
|
||||
|
||||
for (const setting of arcadeOptions) {
|
||||
const value = getNestedValue(arcadeData.value.data, setting.id);
|
||||
setNestedValue(optionForm.value, setting.id, value);
|
||||
setNestedValue(bareForm.value, setting.id, value);
|
||||
}
|
||||
loading.value = false;
|
||||
} catch (error) {
|
||||
console.log("Failed to fetch arcade data:", error);
|
||||
console.error("Failed to fetch arcade data:", error);
|
||||
}
|
||||
}
|
||||
|
||||
async function updateArcade() {
|
||||
const response = await APIUpdateArcade(arcadeId, optionForm.value);
|
||||
|
||||
if (response.status != "error") {
|
||||
await loadArcade();
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadArcade();
|
||||
});
|
||||
|
||||
function formatName(inputString, replaceWith = "NA_") {
|
||||
|
|
@ -52,7 +103,7 @@ function formatName(inputString, replaceWith = "NA_") {
|
|||
|
||||
async function exportVPN() {
|
||||
try {
|
||||
const data = await mainStore.getArcadeVPN(arcadeId);
|
||||
const data = await APIGetArcadeVPN(arcadeId);
|
||||
const blob = new Blob([data], { type: "application/ovpn" });
|
||||
const link = document.createElement("a");
|
||||
link.href = URL.createObjectURL(blob);
|
||||
|
|
@ -76,9 +127,13 @@ async function exportVPN() {
|
|||
<template v-if="!loading">
|
||||
<ArcadeCard class="mb-6" :arcade="arcadeData" />
|
||||
|
||||
<SectionTitleLine :icon="mdiStore" title="Arcade Overview" main />
|
||||
<SectionTitleLine
|
||||
:icon="mdiStoreCog"
|
||||
title="Arcade Administration"
|
||||
main
|
||||
/>
|
||||
|
||||
<CardBox is-form class="mb-6" @submit.prevent="">
|
||||
<CardBox is-form class="mb-6" @submit.prevent="updateArcade">
|
||||
<PillTag
|
||||
color="info"
|
||||
label="Settings"
|
||||
|
|
@ -89,155 +144,57 @@ async function exportVPN() {
|
|||
class="grid grid-cols-1 w-full gap-2 md:gap-6 md:flex md:place-content-stretch"
|
||||
>
|
||||
<FormField
|
||||
label="PASELI Enabled"
|
||||
help="Enable or disable PASELI services."
|
||||
v-for="setting of arcadeOptions"
|
||||
:key="setting.id"
|
||||
:label="setting.name"
|
||||
:help="setting.help"
|
||||
>
|
||||
<FormCheckRadio
|
||||
v-model="arcadeData.data.paseli_enabled"
|
||||
:input-value="arcadeData.data.paseli_enabled"
|
||||
name="paseli"
|
||||
type="switch"
|
||||
/>
|
||||
</FormField>
|
||||
<FormField
|
||||
label="Infinite PASELI"
|
||||
help="Enable or disable infinite PASELI."
|
||||
>
|
||||
<FormCheckRadio
|
||||
v-model="arcadeData.data.paseli_infinite"
|
||||
:input-value="arcadeData.data.paseli_infinite"
|
||||
name="infinitePaseli"
|
||||
type="switch"
|
||||
/>
|
||||
</FormField>
|
||||
<FormField
|
||||
label="Maintenance Mode"
|
||||
help="Place this arcade under Maintenance."
|
||||
>
|
||||
<FormCheckRadio
|
||||
v-model="arcadeData.data.maint"
|
||||
:input-value="arcadeData.data.maint"
|
||||
name="maintenance"
|
||||
type="switch"
|
||||
/>
|
||||
</FormField>
|
||||
<FormField
|
||||
label="Incognito Mode"
|
||||
help="Hide the eAmusement network and ranking data."
|
||||
>
|
||||
<FormCheckRadio
|
||||
v-model="arcadeData.data.hide_network"
|
||||
:input-value="arcadeData.data.hide_network"
|
||||
name="incognito"
|
||||
v-if="setting.type == 'Boolean'"
|
||||
:name="setting.id"
|
||||
:model-value="
|
||||
Boolean(getNestedValue(optionForm, setting.id) ?? 0)
|
||||
"
|
||||
:input-value="true"
|
||||
type="switch"
|
||||
@update:model-value="
|
||||
(value) =>
|
||||
setNestedValue(optionForm, setting.id, Number(value) ?? 0)
|
||||
"
|
||||
/>
|
||||
</FormField>
|
||||
</div>
|
||||
<BaseButton color="success" type="submit" label="Save" />
|
||||
<div
|
||||
v-if="JSON.stringify(optionForm) !== JSON.stringify(bareForm)"
|
||||
class="space-x-2 mt-6"
|
||||
>
|
||||
<BaseButton color="success" label="Save" type="submit" />
|
||||
<BaseButton color="danger" label="Revert" @click="loadArcade()" />
|
||||
</div>
|
||||
</CardBox>
|
||||
|
||||
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2 mb-6">
|
||||
<CardBox>
|
||||
<h1 class="text-lg md:text-xl">OpenVPN Configuration</h1>
|
||||
<p class="pb-1 dark:text-white/50">
|
||||
Use this to export your VPN config.
|
||||
</p>
|
||||
<BaseButton
|
||||
:small="false"
|
||||
color="success"
|
||||
class="my-2"
|
||||
label="Export"
|
||||
@click="exportVPN()"
|
||||
/>
|
||||
</CardBox>
|
||||
|
||||
<!-- <CardBox>
|
||||
<h1 class="text-lg md:text-xl">Cover Photo</h1>
|
||||
<p class="pb-1 dark:text-white/50">
|
||||
NSFW = BAN. Children use this server. 60MB max.
|
||||
</p>
|
||||
<FormFilePicker label="Upload" name="upload" accept="image/*" />
|
||||
|
||||
<BaseButton
|
||||
:small="false"
|
||||
color="success"
|
||||
class="mt-4"
|
||||
label="Save"
|
||||
/>
|
||||
</CardBox> -->
|
||||
|
||||
<!-- <CardBox>
|
||||
<h1 class="text-lg md:text-xl mb-2">Location Settings</h1>
|
||||
|
||||
<FormField label="Area" help="Set your arcade's area.">
|
||||
<FormControl
|
||||
v-model="thisArcade.area"
|
||||
name="area"
|
||||
:options="listCodes()"
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField label="Address" help="Set your arcade's address.">
|
||||
<FormControl
|
||||
v-model="thisArcade.address"
|
||||
name="address"
|
||||
placeholder="No address"
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField
|
||||
label="Show Address"
|
||||
help="Allow your arcade's address to be seen publicly."
|
||||
>
|
||||
<FormCheckRadio
|
||||
:model-value="thisArcade.show_address"
|
||||
:input-value="thisArcade.show_address"
|
||||
name="show_address"
|
||||
type="switch"
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<CardBox class="w-1/2 mb-6">
|
||||
<h1 class="text-lg md:text-xl">OpenVPN Configuration</h1>
|
||||
<p class="pb-1 dark:text-white/50">
|
||||
Use this to download your VPN config.
|
||||
</p>
|
||||
<BaseButton
|
||||
:small="false"
|
||||
color="success"
|
||||
class="mt-4"
|
||||
label="Save"
|
||||
class="my-2"
|
||||
label="Export"
|
||||
@click="exportVPN()"
|
||||
/>
|
||||
</CardBox> -->
|
||||
</div>
|
||||
</CardBox>
|
||||
|
||||
<!-- <SectionTitleLine
|
||||
:icon="mdiChartTimelineVariant"
|
||||
title="Arcade Overview"
|
||||
main
|
||||
/>
|
||||
<SectionTitleLine :icon="mdiStore" title="Arcade Overview" main />
|
||||
|
||||
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2 md:grid-cols-3 mb-6">
|
||||
<CardBoxWidget
|
||||
trend="12% (from last week)"
|
||||
trend-type="up"
|
||||
:number="37"
|
||||
label="Arcade Scores (This Week)"
|
||||
:number="arcadeData?.machines?.length"
|
||||
label="Active Machines"
|
||||
/>
|
||||
<CardBoxWidget
|
||||
trend="40% (from last month)"
|
||||
trend-type="up"
|
||||
:number="3"
|
||||
label="Unique Games (All Time)"
|
||||
/>
|
||||
<CardBoxWidget
|
||||
trend="No new players this week"
|
||||
:number="2"
|
||||
label="Unique Players (All Time)"
|
||||
/>
|
||||
<CardBoxWidget
|
||||
trend="40% (from last month)"
|
||||
trend-type="up"
|
||||
:number="123456789"
|
||||
:prefix="'¥'"
|
||||
label="PASELI Spent (This Month)"
|
||||
/>
|
||||
</div> -->
|
||||
</div>
|
||||
</template>
|
||||
</SectionMain>
|
||||
</LayoutAuthenticated>
|
||||
|
|
|
|||
|
|
@ -12,23 +12,47 @@ import FormControl from "@/components/FormControl.vue";
|
|||
import FormCheckRadio from "@/components/FormCheckRadio.vue";
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import { gameData, getGameInfo } from "@/constants";
|
||||
import { useMainStore } from "@/stores/main";
|
||||
import { getNestedValue, setNestedValue } from "@/constants/values";
|
||||
import { APIGetArcade } from "@/stores/api/arcade";
|
||||
|
||||
const mainStore = useMainStore();
|
||||
const arcadeData = ref({});
|
||||
const optionForm = ref(null);
|
||||
const bareForm = ref(null);
|
||||
const arcadeData = ref(null);
|
||||
const loading = ref(true);
|
||||
|
||||
const $route = useRoute();
|
||||
const arcadeId = parseInt($route.params.id);
|
||||
|
||||
onMounted(async () => {
|
||||
var arcadeOptions = [
|
||||
{
|
||||
id: "data.paseli_enabled",
|
||||
name: "PASELI Enabled.",
|
||||
help: "Enable PASELI for this arcade.",
|
||||
type: "Boolean",
|
||||
},
|
||||
];
|
||||
|
||||
async function loadArcade() {
|
||||
try {
|
||||
const data = await mainStore.getArcade(arcadeId);
|
||||
arcadeData.value = null;
|
||||
optionForm.value = {};
|
||||
bareForm.value = {};
|
||||
const data = await APIGetArcade(arcadeId);
|
||||
arcadeData.value = data;
|
||||
|
||||
for (const setting of arcadeOptions) {
|
||||
const value = getNestedValue(arcadeData.value, setting.id);
|
||||
setNestedValue(optionForm.value, setting.id, value);
|
||||
setNestedValue(bareForm.value, setting.id, value);
|
||||
}
|
||||
loading.value = false;
|
||||
} catch (error) {
|
||||
console.log("Failed to fetch arcade data:", error);
|
||||
console.error("Failed to fetch arcade data:", error);
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadArcade();
|
||||
});
|
||||
|
||||
const eventSettings = [
|
||||
|
|
|
|||
|
|
@ -8,23 +8,27 @@ import LayoutAuthenticated from "@/layouts/LayoutAuthenticated.vue";
|
|||
import SectionTitleLine from "@/components/SectionTitleLine.vue";
|
||||
import ArcadeCard from "@/components/ArcadeCard.vue";
|
||||
import GeneralTable from "@/components/GeneralTable.vue";
|
||||
import { useMainStore } from "@/stores/main";
|
||||
import { APIGetArcade } from "@/stores/api/arcade";
|
||||
|
||||
const mainStore = useMainStore();
|
||||
const arcadeData = ref({});
|
||||
const loading = ref(true);
|
||||
|
||||
const $route = useRoute();
|
||||
const arcadeId = parseInt($route.params.id);
|
||||
|
||||
onMounted(async () => {
|
||||
async function loadArcade() {
|
||||
try {
|
||||
const data = await mainStore.getArcade(arcadeId);
|
||||
arcadeData.value = null;
|
||||
const data = await APIGetArcade(arcadeId);
|
||||
arcadeData.value = data;
|
||||
loading.value = false;
|
||||
} catch (error) {
|
||||
console.log("Failed to fetch arcade data:", error);
|
||||
console.error("Failed to fetch arcade data:", error);
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadArcade();
|
||||
});
|
||||
|
||||
const headers = [
|
||||
|
|
|
|||
|
|
@ -8,9 +8,8 @@ import CardBox from "@/components/CardBox.vue";
|
|||
import LayoutAuthenticated from "@/layouts/LayoutAuthenticated.vue";
|
||||
import SectionTitleLine from "@/components/SectionTitleLine.vue";
|
||||
import ArcadeCard from "@/components/ArcadeCard.vue";
|
||||
import { useMainStore } from "@/stores/main";
|
||||
import { APIGetArcade, APIGetArcadePASELI } from "@/stores/api/arcade";
|
||||
|
||||
const mainStore = useMainStore();
|
||||
const arcadeData = ref({});
|
||||
const paseliData = ref({});
|
||||
const loading = ref(true);
|
||||
|
|
@ -18,16 +17,31 @@ const loading = ref(true);
|
|||
const $route = useRoute();
|
||||
const arcadeId = parseInt($route.params.id);
|
||||
|
||||
onMounted(async () => {
|
||||
async function loadArcade() {
|
||||
try {
|
||||
const loadArcadeData = await mainStore.getArcade(arcadeId);
|
||||
const loadPaseliData = await mainStore.getPaseliData(arcadeId);
|
||||
arcadeData.value = loadArcadeData;
|
||||
paseliData.value = loadPaseliData;
|
||||
arcadeData.value = null;
|
||||
const data = await APIGetArcade(arcadeId);
|
||||
arcadeData.value = data;
|
||||
loading.value = false;
|
||||
} catch (error) {
|
||||
console.log("Failed to fetch arcade data:", error);
|
||||
console.error("Failed to fetch arcade data:", error);
|
||||
}
|
||||
}
|
||||
|
||||
async function loadPASELI() {
|
||||
try {
|
||||
paseliData.value = null;
|
||||
const data = await APIGetArcadePASELI(arcadeId);
|
||||
paseliData.value = data;
|
||||
loading.value = false;
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch arcade PASELI:", error);
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadArcade();
|
||||
loadPASELI();
|
||||
});
|
||||
|
||||
const transactionHeaders = [
|
||||
|
|
|
|||
|
|
@ -16,6 +16,12 @@ import QproCardBox from "@/components/Cards/QproCardBox.vue";
|
|||
import PillTag from "@/components/PillTag.vue";
|
||||
|
||||
import { APIGetProfile, APIUpdateProfile } from "@/stores/api/profile";
|
||||
import {
|
||||
getNestedValue,
|
||||
setNestedValue,
|
||||
transformNonUnicode,
|
||||
transformUnicode,
|
||||
} from "@/constants/values";
|
||||
import { getGameInfo } from "@/constants";
|
||||
import { getVideoSource, getCardStyle } from "@/constants/sources";
|
||||
import { getGameOptions } from "@/constants/options";
|
||||
|
|
@ -96,67 +102,6 @@ async function loadProfile() {
|
|||
}
|
||||
}
|
||||
|
||||
function getNestedValue(obj, path) {
|
||||
return path.split(".").reduce((acc, part) => acc && acc[part], obj);
|
||||
}
|
||||
|
||||
function setNestedValue(obj, path, value) {
|
||||
const keys = path.split(".");
|
||||
const lastKey = keys.pop();
|
||||
const nestedObj = keys.reduce((acc, key) => (acc[key] = acc[key] || {}), obj);
|
||||
nestedObj[lastKey] = value;
|
||||
}
|
||||
|
||||
function transformNonUnicode(value, maxLength) {
|
||||
const allowedCharsRegex = /^[0-9A-Z!?#$&*-. ]*$/;
|
||||
const transformedValue = value.toUpperCase().slice(0, maxLength);
|
||||
|
||||
return (
|
||||
allowedCharsRegex.test(transformedValue) ? transformedValue : ""
|
||||
).toUpperCase();
|
||||
}
|
||||
|
||||
function transformUnicode(value, maxLength) {
|
||||
let transformedValue = "";
|
||||
|
||||
for (
|
||||
let i = 0;
|
||||
i < value.length && transformedValue.length < maxLength;
|
||||
i++
|
||||
) {
|
||||
let c = value.charCodeAt(i);
|
||||
if (c >= 0x30 && c <= 0x39) {
|
||||
// '0' to '9'
|
||||
c = 0xff10 + (c - 0x30);
|
||||
} else if (c >= 0x41 && c <= 0x5a) {
|
||||
// 'A' to 'Z'
|
||||
c = 0xff21 + (c - 0x41);
|
||||
} else if (c >= 0x61 && c <= 0x7a) {
|
||||
// 'a' to 'z'
|
||||
c = 0xff41 + (c - 0x61);
|
||||
} else if (c === 0x40) {
|
||||
// '@'
|
||||
c = 0xff20;
|
||||
} else if (c === 0x2c) {
|
||||
// ','
|
||||
c = 0xff0c;
|
||||
} else if (c === 0x2e) {
|
||||
// '.'
|
||||
c = 0xff0e;
|
||||
} else if (c === 0x5f) {
|
||||
// '_'
|
||||
c = 0xff3f;
|
||||
}
|
||||
transformedValue += String.fromCharCode(c);
|
||||
}
|
||||
|
||||
const allowedCharsRegex =
|
||||
/^[\uFF20-\uFF3A\uFF41-\uFF5A\uFF10-\uFF19\uFF0C\uFF0E\uFF3F\u3041-\u308D\u308F\u3092\u3093\u30A1-\u30ED\u30EF\u30F2\u30F3\u30FC]*$/;
|
||||
return (
|
||||
allowedCharsRegex.test(transformedValue) ? transformedValue : ""
|
||||
).toUpperCase();
|
||||
}
|
||||
|
||||
async function updateProfile() {
|
||||
const response = await APIUpdateProfile(
|
||||
thisGame.id,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user