mirror of
https://github.com/PhaseII-eAmusement-Network/PhaseWeb3-Vue.git
synced 2026-07-20 18:09:42 -05:00
Add final stickerboard support
This commit is contained in:
parent
d11249636a
commit
f4cb9196c3
|
|
@ -2,12 +2,13 @@
|
|||
import axios from "axios";
|
||||
import { watch, ref, reactive } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { mdiLoading } from "@mdi/js";
|
||||
import { mdiLoading, mdiChevronDown, mdiChevronUp } from "@mdi/js";
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import CardBox from "@/components/CardBox.vue";
|
||||
import FormField from "@/components/FormField.vue";
|
||||
import FormControl from "@/components/FormControl.vue";
|
||||
import FormSlider from "@/components/FormSlider.vue";
|
||||
import UserSticker from "@/components/UserSticker.vue";
|
||||
import PillTag from "@/components/PillTag.vue";
|
||||
|
||||
|
|
@ -39,6 +40,9 @@ const newTrbitem = reactive(
|
|||
const trbitemSettings = ref([]);
|
||||
const isModified = ref(false);
|
||||
const loading = ref(false);
|
||||
const collapsedStickers = ref(
|
||||
Array.isArray(newTrbitem.stickers) ? newTrbitem.stickers.map(() => true) : []
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.version,
|
||||
|
|
@ -46,9 +50,14 @@ watch(
|
|||
userProfile.value = props.profile;
|
||||
version.value = props.version;
|
||||
loadTrbitemSettings();
|
||||
newTrbitem.value = JSON.parse(
|
||||
const newProfileData = JSON.parse(
|
||||
JSON.stringify(userProfile.value?.trbitem ?? {})
|
||||
);
|
||||
Object.assign(newTrbitem, newProfileData);
|
||||
// Set all stickers to collapsed when version changes
|
||||
collapsedStickers.value = Array.isArray(newTrbitem.stickers)
|
||||
? newTrbitem.stickers.map(() => true)
|
||||
: [];
|
||||
isModified.value = false;
|
||||
}
|
||||
);
|
||||
|
|
@ -107,25 +116,125 @@ function revert() {
|
|||
);
|
||||
isModified.value = false;
|
||||
}
|
||||
|
||||
function addSticker() {
|
||||
newTrbitem.stickers.push({
|
||||
sticker_id: 24,
|
||||
sticker_pos_x: 160,
|
||||
sticker_pos_y: 277,
|
||||
sticker_scale_x: 1,
|
||||
sticker_scale_y: 1,
|
||||
sticker_rotate: 0,
|
||||
});
|
||||
collapsedStickers.value.push(false);
|
||||
isModified.value = true;
|
||||
}
|
||||
|
||||
function removeSticker(index) {
|
||||
newTrbitem.stickers.splice(index, 1);
|
||||
collapsedStickers.value.splice(index, 1);
|
||||
isModified.value = true;
|
||||
}
|
||||
|
||||
function toggleStickerCollapse(index) {
|
||||
collapsedStickers.value[index] = !collapsedStickers.value[index];
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<CardBox class="mt-6">
|
||||
<PillTag color="info" label="Sticker Board" class="mb-2" />
|
||||
<div class="grid md:grid-cols-2 space-y-6 align-center">
|
||||
<form>
|
||||
<div class="grid md:grid-cols-2 xl:grid-cols-3 space-y-6 align-center">
|
||||
<div class="col-span-1 xl:col-span-2">
|
||||
<FormField key="base" label="Base">
|
||||
<FormControl
|
||||
v-model="newTrbitem.base"
|
||||
:options="trbitemSettings.base"
|
||||
/>
|
||||
</FormField>
|
||||
</form>
|
||||
|
||||
<div class="space-y-4">
|
||||
<CardBox
|
||||
v-for="(sticker, index) in newTrbitem.stickers ?? []"
|
||||
:key="sticker.sticker_id"
|
||||
color-prop="bg-slate-600 dark:bg-slate-800"
|
||||
>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-lg">Sticker {{ index + 1 }}</span>
|
||||
<BaseButton
|
||||
:icon="collapsedStickers[index] ? mdiChevronDown : mdiChevronUp"
|
||||
color="info"
|
||||
@click="toggleStickerCollapse(index)"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="!collapsedStickers[index]" class="p-2">
|
||||
<div class="w-full grid grid-cols-2 lg:grid-cols-5 gap-2 pt-2">
|
||||
<FormField label="Sticker" class="col-span-2 lg:col-span-5">
|
||||
<FormControl
|
||||
v-model="sticker.sticker_id"
|
||||
:options="trbitemSettings.sticker"
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField label="Position X">
|
||||
<FormSlider
|
||||
v-model="sticker.sticker_pos_x"
|
||||
name="sticker_pos_x"
|
||||
:min="0"
|
||||
:max="320"
|
||||
:step="1"
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField label="Position Y">
|
||||
<FormSlider
|
||||
v-model="sticker.sticker_pos_y"
|
||||
name="sticker_pos_y"
|
||||
:min="0"
|
||||
:max="554"
|
||||
:step="1"
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField label="Scale">
|
||||
<FormSlider
|
||||
v-model="sticker.sticker_scale_x"
|
||||
name="sticker_scale_x"
|
||||
:min="0.5"
|
||||
:max="2"
|
||||
:step="0.01"
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField label="Rotation">
|
||||
<FormSlider
|
||||
v-model="sticker.sticker_rotate"
|
||||
name="sticker_rotate"
|
||||
:min="-180"
|
||||
:max="180"
|
||||
:step="1"
|
||||
/>
|
||||
</FormField>
|
||||
</div>
|
||||
<BaseButton
|
||||
color="danger"
|
||||
label="Remove"
|
||||
@click="removeSticker(index)"
|
||||
/>
|
||||
</div>
|
||||
</CardBox>
|
||||
<BaseButton color="info" label="Add Sticker" @click="addSticker()" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="place-self-center">
|
||||
<UserSticker
|
||||
:key="emblemKey"
|
||||
:version="version"
|
||||
:profile="{ trbitem: newTrbitem }"
|
||||
:profile="{
|
||||
trbitem: {
|
||||
...newTrbitem,
|
||||
},
|
||||
}"
|
||||
:size="300"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
52
src/components/FormSlider.vue
Normal file
52
src/components/FormSlider.vue
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
<script setup>
|
||||
import { computed } from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
modelValue: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
min: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
max: {
|
||||
type: Number,
|
||||
default: 100,
|
||||
},
|
||||
step: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(["update:modelValue"]);
|
||||
|
||||
const computedValue = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (value) => {
|
||||
emit("update:modelValue", value);
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<input
|
||||
v-model="computedValue"
|
||||
type="range"
|
||||
:name="name"
|
||||
:min="min"
|
||||
:max="max"
|
||||
:step="step"
|
||||
class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700"
|
||||
/>
|
||||
<span class="font-light">{{ computedValue }}</span>
|
||||
</template>
|
||||
|
|
@ -12,7 +12,7 @@ const props = defineProps({
|
|||
},
|
||||
size: {
|
||||
type: Number,
|
||||
default: 128,
|
||||
default: 320,
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -35,32 +35,34 @@ function getPath(id) {
|
|||
|
||||
function getStickerStyle(sticker) {
|
||||
return {
|
||||
left: `${sticker.sticker_pos_x}px`,
|
||||
top: `${sticker.sticker_pos_y}px`,
|
||||
transform: `scale(${sticker.sticker_scale_x}, ${sticker.sticker_scale_y}) rotate(${sticker.sticker_rotate}deg)`,
|
||||
// Use transform for positioning, scaling, and rotation
|
||||
transform: `translate(${sticker.sticker_pos_x - 150}px, ${
|
||||
sticker.sticker_pos_y - 100
|
||||
}px) scale(${sticker.sticker_scale_x}, ${sticker.sticker_scale_x}) rotate(${
|
||||
sticker.sticker_rotate
|
||||
}deg)`,
|
||||
// Ensure the base position is at the top-left corner of the sticker
|
||||
position: "absolute",
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="inner">
|
||||
<div :style="`position: relative; width: ${size}px; height: 500px`">
|
||||
<div key="base" style="position: absolute">
|
||||
<img
|
||||
:src="getPath(userProfile.trbitem?.base ?? 0)"
|
||||
:style="`width: ${size}px`"
|
||||
class="drop-shadow-lg"
|
||||
/>
|
||||
</div>
|
||||
<div class="relative overflow-hidden w-[320px] h-[554px] border">
|
||||
<!-- Base Image -->
|
||||
<img
|
||||
:src="getPath(userProfile.trbitem?.base ?? 0)"
|
||||
class="absolute w-[320px] h-[554px] drop-shadow-lg"
|
||||
/>
|
||||
|
||||
<div
|
||||
v-for="sticker of userProfile.trbitem?.stickers ?? []"
|
||||
:key="sticker.sticker_id"
|
||||
class="absolute cursor-pointer"
|
||||
:style="getStickerStyle(sticker)"
|
||||
>
|
||||
<img :src="getPath(sticker.sticker_id)" />
|
||||
</div>
|
||||
<!-- Stickers -->
|
||||
<div
|
||||
v-for="sticker in userProfile.trbitem?.stickers ?? []"
|
||||
:key="sticker.sticker_id"
|
||||
class="absolute"
|
||||
:style="getStickerStyle(sticker)"
|
||||
>
|
||||
<img :src="getPath(sticker.sticker_id)" class="w-[300px] h-[300px]" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import {
|
|||
mdiChartBarStacked,
|
||||
mdiChartAreasplineVariant,
|
||||
mdiChartTimeline,
|
||||
mdiStickerOutline,
|
||||
} from "@mdi/js";
|
||||
import SectionMain from "@/components/SectionMain.vue";
|
||||
import CardBoxWidget from "@/components/CardBoxWidget.vue";
|
||||
|
|
@ -20,6 +21,7 @@ import SectionTitleLine from "@/components/SectionTitleLine.vue";
|
|||
import FormControl from "@/components/FormControl.vue";
|
||||
import PillTag from "@/components/PillTag.vue";
|
||||
import JubilityTable from "@/components/Tables/JubilityTable.vue";
|
||||
import UserSticker from "@/components/UserSticker.vue";
|
||||
|
||||
import { APIGetProfile } from "@/stores/api/profile";
|
||||
import { APIGetArcade } from "@/stores/api/arcade";
|
||||
|
|
@ -488,11 +490,7 @@ async function generateTimeline(myProfile) {
|
|||
class="my-6 grid grid-cols-2 md:grid-cols-5 xl:grid-cols-6 gap-6"
|
||||
>
|
||||
<template v-for="stat of formatCounts(myProfile)" :key="stat">
|
||||
<CardBoxWidget
|
||||
v-if="stat.value"
|
||||
:label="stat.label"
|
||||
:number="stat.value"
|
||||
/>
|
||||
<CardBoxWidget v-if="stat" :label="stat.label" :number="stat" />
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -524,6 +522,24 @@ async function generateTimeline(myProfile) {
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="myProfile?.trbitem">
|
||||
<SectionTitleLine
|
||||
:icon="mdiStickerOutline"
|
||||
title="Sticker Board"
|
||||
main
|
||||
/>
|
||||
|
||||
<div class="my-6">
|
||||
<CardBox class="w-full grid place-content-center">
|
||||
<UserSticker
|
||||
:version="versionForm.currentVersion"
|
||||
:profile="myProfile"
|
||||
:size="290"
|
||||
/>
|
||||
</CardBox>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="myProfile?.timeline">
|
||||
<SectionTitleLine :icon="mdiChartTimeline" title="Timeline" main />
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user