push
This commit is contained in:
@@ -48,11 +48,11 @@
|
||||
<input v-model="url" class="opt-input" type="text" placeholder="URL de destination (optionnel)" />
|
||||
</div>
|
||||
|
||||
<!-- Options : Pet (grille + position) -->
|
||||
<!-- Options : Pet (grille des designs non encore possédés) -->
|
||||
<div v-if="product.kind === 'pet'" class="opts">
|
||||
<div class="pet-grid">
|
||||
<button
|
||||
v-for="d in designs"
|
||||
v-for="d in availableDesigns"
|
||||
:key="d.id"
|
||||
class="pet-cell"
|
||||
:class="{ active: petDesign === d.id }"
|
||||
@@ -60,12 +60,11 @@
|
||||
type="button"
|
||||
>{{ d.char }}</button>
|
||||
</div>
|
||||
<div class="pet-pos">
|
||||
<label v-for="pos in positions" :key="pos" class="opt-radio opt-radio--sm" :class="{ active: petPosition === pos }">
|
||||
<input type="radio" :value="pos" v-model="petPosition" />
|
||||
<span>{{ posLabel(pos) }}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Preview : Skin de bouton -->
|
||||
<div v-if="product.kind === 'send-skin'" class="send-skin-preview">
|
||||
<div class="skin-btn-demo">{{ meta.char }}</div>
|
||||
</div>
|
||||
|
||||
<!-- Stock limité -->
|
||||
@@ -107,13 +106,14 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import type { Product, PurchaseOptions } from '@/composables/useShop';
|
||||
|
||||
const props = defineProps<{
|
||||
product: Product;
|
||||
buying: boolean;
|
||||
owns: (kind: string) => boolean;
|
||||
ownedPetChars: string[];
|
||||
petCount: number;
|
||||
freeMode: boolean;
|
||||
}>();
|
||||
@@ -141,11 +141,19 @@ const url = ref('');
|
||||
|
||||
// Pet
|
||||
const designs = computed(() => meta.value.designs ?? []);
|
||||
const positions = computed<string[]>(() => meta.value.positions ?? ['left', 'right', 'both']);
|
||||
const petDesign = ref<string>('');
|
||||
const petPosition = ref<'left' | 'right' | 'both'>('left');
|
||||
const availableDesigns = computed(() =>
|
||||
designs.value.filter((d: any) => !props.ownedPetChars.includes(d.char))
|
||||
);
|
||||
watch(availableDesigns, (ds) => {
|
||||
if (ds.length > 0 && !ds.find((d: any) => d.id === petDesign.value)) {
|
||||
petDesign.value = (ds[0] as any).id;
|
||||
}
|
||||
}, { immediate: true });
|
||||
|
||||
const icon = computed(() => {
|
||||
if (props.product.id === 'ip-colors') return '🎨';
|
||||
if (props.product.kind === 'send-skin') return meta.value.char ?? '🖱️';
|
||||
switch (props.product.kind) {
|
||||
case 'ad-frame': return '📣';
|
||||
case 'subscription': return '🚫';
|
||||
@@ -180,6 +188,7 @@ const ownedAlready = computed(() => {
|
||||
if (k === 'rich') return props.owns(props.product.id);
|
||||
if (k === 'unlock') return props.owns(props.product.id);
|
||||
if (k === 'ad-frame') return props.owns('ad-frame');
|
||||
if (k === 'send-skin') return props.owns(props.product.id);
|
||||
return false;
|
||||
});
|
||||
|
||||
@@ -201,9 +210,6 @@ const stockPct = computed(() =>
|
||||
function fmt(centi: number): string {
|
||||
return (centi / 100).toLocaleString('fr-FR', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
||||
}
|
||||
function posLabel(p: string): string {
|
||||
return p === 'left' ? 'Gauche' : p === 'right' ? 'Droite' : 'Les deux';
|
||||
}
|
||||
|
||||
function onBuy(): void {
|
||||
const options: PurchaseOptions = {};
|
||||
@@ -214,9 +220,8 @@ function onBuy(): void {
|
||||
options.url = url.value || undefined;
|
||||
}
|
||||
if (props.product.kind === 'pet' || props.product.id === 'bundle-cosmetic') {
|
||||
const d = designs.value.find((x: any) => x.id === petDesign.value) ?? designs.value[0];
|
||||
if (d) { options.petDesign = d.id; options.petChar = d.char; }
|
||||
options.petPosition = petPosition.value;
|
||||
const d = availableDesigns.value.find((x: any) => x.id === petDesign.value) ?? availableDesigns.value[0];
|
||||
if (d) { options.petDesign = (d as any).id; options.petChar = (d as any).char; }
|
||||
}
|
||||
emit('buy', props.product.id, options);
|
||||
}
|
||||
@@ -291,6 +296,14 @@ function onBuy(): void {
|
||||
.pet-cell.active { border-color: #8844aa; }
|
||||
.pet-pos { display: flex; gap: 6px; }
|
||||
|
||||
.send-skin-preview { display: flex; justify-content: center; padding: 8px 0; }
|
||||
.skin-btn-demo {
|
||||
width: 52px; height: 52px; border-radius: 50%;
|
||||
background: #151525; border: 1px solid #30306a;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.stock { display: flex; flex-direction: column; gap: 4px; }
|
||||
.stock-bar { height: 6px; background: #1a1a2a; border-radius: 3px; overflow: hidden; }
|
||||
.stock-fill { height: 100%; background: linear-gradient(90deg, #ffaa00, #ff4444); }
|
||||
|
||||
Reference in New Issue
Block a user