fix: 1:1 prototype port – exact hms-* CSS, real logo, all components from app.js
This commit is contained in:
@@ -1,87 +1,22 @@
|
||||
<template>
|
||||
<article
|
||||
class="card rounded-lg overflow-hidden border border-border-default hover:border-accent-border transition-colors duration-fast flex flex-col"
|
||||
data-testid="equipment-card"
|
||||
>
|
||||
<!-- Image / Placeholder -->
|
||||
<div class="relative w-full h-48 bg-surface overflow-hidden">
|
||||
<img
|
||||
v-if="equipment.image_url"
|
||||
:src="equipment.image_url"
|
||||
:alt="equipment.name"
|
||||
class="w-full h-full object-cover"
|
||||
loading="lazy"
|
||||
/>
|
||||
<div
|
||||
v-else
|
||||
class="w-full h-full flex items-center justify-center"
|
||||
>
|
||||
<svg class="w-12 h-12 text-secondary" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 15.75l5.159-5.159a2.25 2.25 0 013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0 013.182 0l2.909 2.909M3.75 3.75h16.5a1.5 1.5 0 011.5 1.5v12a1.5 1.5 0 01-1.5 1.5H3.75a1.5 1.5 0 01-1.5-1.5V5.25a1.5 1.5 0 011.5-1.5z" />
|
||||
</svg>
|
||||
</div>
|
||||
<!-- Category Badge -->
|
||||
<span
|
||||
v-if="equipment.category"
|
||||
class="absolute top-2 left-2 px-2 py-1 text-xs font-medium rounded-sm bg-bg/80 text-text-muted backdrop-blur-sm"
|
||||
>
|
||||
{{ equipment.category }}
|
||||
</span>
|
||||
<!-- Availability Badge -->
|
||||
<span
|
||||
v-if="!equipment.available"
|
||||
class="absolute top-2 right-2 px-2 py-1 text-xs font-medium rounded-sm bg-error-bg text-error"
|
||||
>
|
||||
Nicht verfügbar
|
||||
</span>
|
||||
<div class="hms-eq-card" @click="$emit('click', item)" role="article" tabindex="0" @keydown.enter="$emit('click', item)">
|
||||
<div class="aspect-[4/3] flex items-center justify-center relative overflow-hidden" style="background: var(--surface)">
|
||||
<img v-if="item.image" :src="item.image" :alt="item.name" loading="lazy" class="absolute inset-0 w-full h-full object-cover" />
|
||||
<div v-else class="text-4xl" style="color: var(--secondary)">📦</div>
|
||||
<span v-if="item.category" class="hms-badge hms-badge-primary absolute top-3 left-3">{{ item.category }}</span>
|
||||
</div>
|
||||
|
||||
<!-- Content -->
|
||||
<div class="flex flex-col flex-grow p-4">
|
||||
<h3 class="text-base font-bold text-text mb-1 line-clamp-1">
|
||||
<NuxtLink :to="`/mietkatalog/${equipment.id}`" class="hover:text-accent transition-colors duration-fast">
|
||||
{{ equipment.name }}
|
||||
</NuxtLink>
|
||||
</h3>
|
||||
<p class="text-sm text-text-muted mb-3 line-clamp-2 flex-grow">
|
||||
{{ equipment.description || "Keine Beschreibung verfügbar" }}
|
||||
</p>
|
||||
|
||||
<!-- Price & Button -->
|
||||
<div class="flex items-center justify-between mt-2">
|
||||
<span v-if="equipment.rental_price != null" class="text-sm font-semibold text-accent">
|
||||
{{ formatPrice(equipment.rental_price) }} €/Tag
|
||||
</span>
|
||||
<span v-else class="text-sm text-text-muted">
|
||||
Preis auf Anfrage
|
||||
</span>
|
||||
<button
|
||||
class="btn-primary text-xs px-3 py-2"
|
||||
@click="$emit('add-to-cart', { id: equipment.id, name: equipment.name })"
|
||||
>
|
||||
Mietanfrage
|
||||
</button>
|
||||
<div class="p-4">
|
||||
<h3 class="font-semibold text-sm mb-1 truncate" style="color: var(--text)">{{ item.name }}</h3>
|
||||
<p class="text-xs mb-3 line-clamp-2" style="color: var(--secondary)">{{ item.description }}</p>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-xs" style="color: var(--secondary)">{{ item.code }}</span>
|
||||
<button @click.stop="$emit('add-to-cart', item)" class="hms-btn hms-btn-ghost text-xs px-3 py-1.5" style="color: var(--color-accent)" :aria-label="item.name + ' zum Warenkorb hinzufügen'">+ Hinzufügen</button>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { EquipmentItem } from "~/composables/useEquipment";
|
||||
|
||||
const props = defineProps<{
|
||||
equipment: EquipmentItem;
|
||||
}>();
|
||||
|
||||
defineEmits<{
|
||||
"add-to-cart": [{ id: number; name: string }];
|
||||
}>();
|
||||
|
||||
function formatPrice(price: number | null): string {
|
||||
if (price == null) return "—";
|
||||
return new Intl.NumberFormat("de-DE", {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
}).format(price);
|
||||
}
|
||||
defineProps<{ item: Record<string, any> }>()
|
||||
defineEmits<{ click: [item: any]; 'add-to-cart': [item: any] }>()
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user