You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
116 lines
3.4 KiB
116 lines
3.4 KiB
<script setup lang="ts">
|
|
import { cn } from '~/lib/utils'
|
|
import type { CartItemWithProduct } from '~/types/cart'
|
|
|
|
interface Props {
|
|
/**
|
|
* Cart items for summary calculation
|
|
*/
|
|
items: CartItemWithProduct[]
|
|
/**
|
|
* Total amount in EUR
|
|
*/
|
|
total: number
|
|
/**
|
|
* Loading state (e.g., during checkout)
|
|
*/
|
|
loading?: boolean
|
|
/**
|
|
* Additional CSS classes
|
|
*/
|
|
class?: string
|
|
}
|
|
|
|
const props = defineProps<Props>()
|
|
|
|
// Format currency in EUR
|
|
const formatCurrency = (amount: number) => {
|
|
return new Intl.NumberFormat('de-DE', {
|
|
style: 'currency',
|
|
currency: 'EUR',
|
|
}).format(amount)
|
|
}
|
|
|
|
// Calculate item count
|
|
const itemCount = computed(() => {
|
|
return props.items.reduce((sum, item) => sum + item.quantity, 0)
|
|
})
|
|
|
|
// Calculate VAT (7% already included in total)
|
|
// Formula: VAT = total * (VAT_rate / (1 + VAT_rate))
|
|
const vatAmount = computed(() => {
|
|
return props.total * (0.07 / 1.07)
|
|
})
|
|
|
|
// Format values
|
|
const formattedSubtotal = computed(() => formatCurrency(props.total))
|
|
const formattedVat = computed(() => formatCurrency(vatAmount.value))
|
|
const formattedTotal = computed(() => formatCurrency(props.total))
|
|
|
|
// Item count text (singular/plural)
|
|
const itemCountText = computed(() => {
|
|
return itemCount.value === 1 ? '1 Artikel' : `${itemCount.value} Artikel`
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<Card :class="cn('sticky top-4', props.class)">
|
|
<div class="p-6 space-y-4">
|
|
<!-- Header -->
|
|
<div>
|
|
<h2 class="text-xl font-bold text-white">Zusammenfassung</h2>
|
|
<p class="text-sm text-white/60 mt-1">{{ itemCountText }}</p>
|
|
</div>
|
|
|
|
<Separator class="bg-white/20" />
|
|
|
|
<!-- Price Breakdown -->
|
|
<div class="space-y-3">
|
|
<!-- Subtotal -->
|
|
<div class="flex items-center justify-between text-white/80">
|
|
<span class="text-sm">Zwischensumme</span>
|
|
<span class="font-medium">{{ formattedSubtotal }}</span>
|
|
</div>
|
|
|
|
<!-- VAT (included) -->
|
|
<div class="flex items-center justify-between text-white/60 text-sm">
|
|
<span>inkl. MwSt. (7%)</span>
|
|
<span>{{ formattedVat }}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<Separator class="bg-white/20" />
|
|
|
|
<!-- Total -->
|
|
<div class="flex items-center justify-between">
|
|
<span class="text-lg font-bold text-white">Gesamt</span>
|
|
<span class="text-2xl font-bold text-experimenta-accent">
|
|
{{ formattedTotal }}
|
|
</span>
|
|
</div>
|
|
|
|
<!-- Checkout Button -->
|
|
<Button
|
|
class="w-full bg-gradient-button bg-size-300 bg-left hover:bg-right transition-all duration-300 font-bold text-white shadow-lg hover:shadow-2xl"
|
|
size="lg" :disabled="loading || items.length === 0" @click="$emit('checkout')">
|
|
<span v-if="!loading">Zur Kasse</span>
|
|
<span v-else class="flex items-center gap-2">
|
|
<div class="animate-spin rounded-full h-4 w-4 border-2 border-white/20 border-t-white" />
|
|
Wird verarbeitet...
|
|
</span>
|
|
</Button>
|
|
|
|
<!-- Additional Info -->
|
|
<!-- <div class="pt-2 space-y-2 text-xs text-white/60">
|
|
<p class="flex items-start gap-2">
|
|
<span class="text-experimenta-accent">✓</span>
|
|
<span>Sichere Zahlung mit PayPal</span>
|
|
</p>
|
|
<p class="flex items-start gap-2">
|
|
<span class="text-experimenta-accent">✓</span>
|
|
<span>Versandkostenfrei</span>
|
|
</p>
|
|
</div> -->
|
|
</div>
|
|
</Card>
|
|
</template>
|
|
|