<template> <article class="PriceCard roboto-condensed" v-ripple="{ color: 'rgba(0, 0, 0, 0.1)' }"> <div class="bottom"> <div class="bg-edit"> <Icon class="icon" name="uil:pen" mode="svg" /> </div> <div class="bg-delete"> <Icon class="icon" name="uil:trash-alt" mode="svg" /> </div> </div> <div ref="top" class="top flex-col" :class="{ 'animated' : !isSwiping }" :style="{ left }" @click="update" > <header> <div class="name-price"> <span>{{ card.name || 'Kein Name' }}</span> <span>{{ intl.format(+replaceComma(card.price))}}</span> </div> <div v-if="$device.isDesktop" class="flex-row gap-default"> <PpButton class="icon-button" @click="update"> <Icon class="icon" name="uil:pen" mode="svg" /> </PpButton> <PpButton class="icon-button" @click="deleteCard"> <Icon class="icon" name="uil:trash-alt" mode="svg" /> </PpButton> </div> </header> <main class="wrapper"> <div class="info flex-col"> <div class="price"> <Icon class="icon" name="uil:toilet-paper" mode="svg" /> <span class="value">{{ intl.format(ppr) }}</span> </div> <span class="pro">Pro 1 {{ card.roles ? `(${card.roles})` : '' }}</span> </div> <div class="info flex-col"> <div class="price"> <Icon class="icon" name="uil:file-landscape" mode="svg" /> <span class="value">{{ intl.format(pps) }}</span> </div> <span class="pro">Pro 100 {{ card.sheets ? `(${card.sheets})` : '' }}</span> </div> <div class="info flex-col"> <div class="price"> <Icon class="icon" name="uil:layer-group" mode="svg" /> <span class="value">{{ intl.format(ppl) }}</span> </div> <span class="pro">Pro 1000 {{ card.layers ? `(${card.layers})` : '' }}</span> </div> </main> </div> </article> </template> <script setup lang="ts"> import type { Card } from '../../../shared/Card' type Props = { deletable: boolean card: Card } const { card } = defineProps<Props>() const emit = defineEmits(['remove', 'update']) const { vibrate } = useVibrate() const top = useTemplateRef('top') const left = shallowRef<string>('0') const intl = Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR', }) const { lengthX, direction, isSwiping } = useSwipe(top, { passive: true, threshold: 20, onSwipe() { if (['down', 'up'].includes(direction.value)) return left.value = `${-clamp(lengthX.value, 0, 100)}px` }, onSwipeEnd() { if (['down', 'up'].includes(direction.value)) return if (lengthX.value > 50) deleteCard() vibrate(100) left.value = '0' }, }) const priceClean = computed<number>(() => +replaceComma(card.price)) const ppr = computed(() => priceClean.value / +card.roles) const pps = computed(() => (ppr.value / +card.sheets) * 100) const ppl = computed(() => (pps.value / +card.layers) * 10) const update = () => emit('update') const deleteCard = () => emit('remove') defineExpose({ ppr, pps, ppl, uuid : card.uuid, }) </script>