refactor(shop): découpe MesPersos en sous-sections + nettoyage ProductCard
All checks were successful
Deploy XIP / deploy (push) Successful in 35s
All checks were successful
Deploy XIP / deploy (push) Successful in 35s
- MesPersos.vue (347L) éclaté en 5 sous-composants autonomes sous shop/persos/ (BgPrefsSection, SendButtonPrefsSection, SendSkinPrefsSection, IpColorPrefsSection, PetsPrefsSection). MesPersos n'est plus qu'un wrapper. - CSS partagé des sections déplacé en classes globales .pf-* dans style.css (plus de duplication entre les sections). - ProductCard : metaJson typé via parseMeta<ProductMeta>(), suppression des casts `any` (find/designs) — comportement identique. - vue-tsc --noEmit : 0 erreur. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -108,6 +108,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import type { Product, PurchaseOptions } from '@/composables/useShop';
|
||||
import { parseMeta, type ProductMeta } from '@/composables/useMeta';
|
||||
|
||||
const props = defineProps<{
|
||||
product: Product;
|
||||
@@ -123,10 +124,7 @@ const emit = defineEmits<{
|
||||
goPerso: [];
|
||||
}>();
|
||||
|
||||
const meta = computed<any>(() => {
|
||||
try { return props.product.metaJson ? JSON.parse(props.product.metaJson) : {}; }
|
||||
catch { return {}; }
|
||||
});
|
||||
const meta = computed(() => parseMeta<ProductMeta>(props.product.metaJson));
|
||||
|
||||
// Subscription
|
||||
const plans = computed(() => meta.value.plans ?? []);
|
||||
@@ -143,11 +141,11 @@ const url = ref('');
|
||||
const designs = computed(() => meta.value.designs ?? []);
|
||||
const petDesign = ref<string>('');
|
||||
const availableDesigns = computed(() =>
|
||||
designs.value.filter((d: any) => !props.ownedPetChars.includes(d.char))
|
||||
designs.value.filter((d) => !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;
|
||||
if (ds.length > 0 && !ds.find((d) => d.id === petDesign.value)) {
|
||||
petDesign.value = ds[0].id;
|
||||
}
|
||||
}, { immediate: true });
|
||||
|
||||
@@ -169,12 +167,12 @@ const icon = computed(() => {
|
||||
const effectivePrice = computed(() => {
|
||||
let price = props.product.promoPrice ?? props.product.basePrice;
|
||||
if (props.product.kind === 'subscription') {
|
||||
const p = plans.value.find((x: any) => x.id === plan.value);
|
||||
const p = plans.value.find((x) => x.id === plan.value);
|
||||
if (p) price = p.price;
|
||||
}
|
||||
if (props.product.kind === 'ad-frame') {
|
||||
const d = durations.value.find((x: any) => x.days === durationDays.value);
|
||||
const f = formats.value.find((x: any) => x.id === format.value);
|
||||
const d = durations.value.find((x) => x.days === durationDays.value);
|
||||
const f = formats.value.find((x) => x.id === format.value);
|
||||
price += (d?.extra ?? 0) + (f?.extra ?? 0);
|
||||
}
|
||||
return price;
|
||||
@@ -220,8 +218,8 @@ function onBuy(): void {
|
||||
options.url = url.value || undefined;
|
||||
}
|
||||
if (props.product.kind === 'pet' || props.product.id === 'bundle-cosmetic') {
|
||||
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; }
|
||||
const d = availableDesigns.value.find((x) => x.id === petDesign.value) ?? availableDesigns.value[0];
|
||||
if (d) { options.petDesign = d.id; options.petChar = d.char; }
|
||||
}
|
||||
emit('buy', props.product.id, options);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user