Browse Source
- Introduced a new page for educator annual passes, displaying relevant products with a dedicated layout and loading/error states. - Updated AreaTabs component to include the educator tab and adjusted routing logic. - Modified useAuth to redirect users to the products page after login. - Adjusted mock product prices and stock quantities in the database seeding script to reflect new pricing strategy. These changes enhance the user experience for educators and improve product visibility in the application.main
4 changed files with 170 additions and 17 deletions
@ -0,0 +1,142 @@ |
|||||
|
<script setup lang="ts"> |
||||
|
/** |
||||
|
* Educator Products Listing Page |
||||
|
* |
||||
|
* Displays educator annual passes using ProductCard and ProductGrid components. |
||||
|
* Fetches only educator category products from the database via API. |
||||
|
*/ |
||||
|
|
||||
|
// Page metadata |
||||
|
definePageMeta({ |
||||
|
layout: 'default', |
||||
|
}) |
||||
|
|
||||
|
// Type definition for product |
||||
|
interface Product { |
||||
|
id: string |
||||
|
navProductId: string |
||||
|
name: string |
||||
|
description: string |
||||
|
price: string |
||||
|
stockQuantity: number |
||||
|
category: string |
||||
|
active: boolean |
||||
|
createdAt: Date |
||||
|
updatedAt: Date |
||||
|
} |
||||
|
|
||||
|
// Fetch products from API - only educator passes |
||||
|
const { data: products, error, pending } = await useFetch<Product[]>('/api/products', { |
||||
|
query: { |
||||
|
category: 'educator-annual-pass', |
||||
|
}, |
||||
|
}) |
||||
|
|
||||
|
// Map product categories to badges |
||||
|
const getBadge = (category: string): string | undefined => { |
||||
|
const badges: Record<string, string> = { |
||||
|
'educator-annual-pass': 'Für Pädagogen', |
||||
|
} |
||||
|
return badges[category] |
||||
|
} |
||||
|
|
||||
|
// Map product categories to discount percentages (for demo) |
||||
|
const getDiscount = (category: string): number | undefined => { |
||||
|
const discounts: Record<string, number> = { |
||||
|
// No discounts for now |
||||
|
} |
||||
|
return discounts[category] |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<template> |
||||
|
<NuxtLayout name="default"> |
||||
|
<div class="min-h-screen bg-gradient-primary px-4 py-12 md:px-6 lg:px-8"> |
||||
|
<!-- Page Header --> |
||||
|
<div class="mx-auto mb-12 max-w-container-wide text-center"> |
||||
|
<h1 class="mb-4 text-4xl font-bold text-white md:text-5xl"> |
||||
|
Pädagogische Jahreskarten |
||||
|
</h1> |
||||
|
<p class="mx-auto max-w-2xl text-lg text-white/80"> |
||||
|
Spezielle Jahreskarten für Pädagogen und Lehrkräfte. |
||||
|
Nutze die experimenta für deine Bildungsarbeit und profitiere von vergünstigten Konditionen. |
||||
|
</p> |
||||
|
</div> |
||||
|
|
||||
|
<!-- Loading State --> |
||||
|
<div v-if="pending" class="mx-auto max-w-container-wide text-center"> |
||||
|
<div class="card-glass inline-block"> |
||||
|
<p class="text-white/80">Produkte werden geladen...</p> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- Error State --> |
||||
|
<div v-else-if="error" class="mx-auto max-w-container-wide"> |
||||
|
<div class="card-glass border-red/50 bg-red/10"> |
||||
|
<h2 class="mb-2 text-xl font-semibold text-red"> |
||||
|
Fehler beim Laden der Produkte |
||||
|
</h2> |
||||
|
<p class="text-white/80"> |
||||
|
{{ error.message || 'Ein unbekannter Fehler ist aufgetreten.' }} |
||||
|
</p> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- Products Grid --> |
||||
|
<div v-else-if="products && products.length > 0" class="mx-auto max-w-container-wide"> |
||||
|
<ProductGrid :columns="3"> |
||||
|
<ProductCard |
||||
|
v-for="product in products" |
||||
|
:key="product.id" |
||||
|
image="/img/makerspace-jk-2025.jpg" |
||||
|
:title="product.name" |
||||
|
:description="product.description" |
||||
|
:price="Number(product.price)" |
||||
|
:badge="getBadge(product.category)" |
||||
|
:discount-percentage="getDiscount(product.category)" |
||||
|
:product-id="product.id" |
||||
|
/> |
||||
|
</ProductGrid> |
||||
|
</div> |
||||
|
|
||||
|
<!-- Empty State --> |
||||
|
<div v-else class="mx-auto max-w-container-wide text-center"> |
||||
|
<div class="card-glass"> |
||||
|
<h2 class="mb-2 text-xl font-semibold text-white"> |
||||
|
Keine Produkte verfügbar |
||||
|
</h2> |
||||
|
<p class="text-white/80"> |
||||
|
Aktuell sind keine Pädagogen-Jahreskarten verfügbar. Bitte schaue später noch einmal vorbei. |
||||
|
</p> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- Info Card --> |
||||
|
<div class="mx-auto mt-12 max-w-container-wide"> |
||||
|
<div class="card-info card-accent-border"> |
||||
|
<h2 class="mb-3 text-xl font-semibold text-experimenta-accent"> |
||||
|
Warum eine Pädagogen-Jahreskarte? |
||||
|
</h2> |
||||
|
<ul class="space-y-2 text-white/90"> |
||||
|
<li class="flex items-start gap-2"> |
||||
|
<span class="mt-1 text-experimenta-accent">✓</span> |
||||
|
<span>Speziell für Lehrkräfte und Pädagogen entwickelt</span> |
||||
|
</li> |
||||
|
<li class="flex items-start gap-2"> |
||||
|
<span class="mt-1 text-experimenta-accent">✓</span> |
||||
|
<span>Vergünstigte Konditionen für Bildungseinrichtungen</span> |
||||
|
</li> |
||||
|
<li class="flex items-start gap-2"> |
||||
|
<span class="mt-1 text-experimenta-accent">✓</span> |
||||
|
<span>Ideal für Schulausflüge und Projektwochen</span> |
||||
|
</li> |
||||
|
<li class="flex items-start gap-2"> |
||||
|
<span class="mt-1 text-experimenta-accent">✓</span> |
||||
|
<span>Flexible Nutzung für deine Bildungsarbeit</span> |
||||
|
</li> |
||||
|
</ul> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</NuxtLayout> |
||||
|
</template> |
||||
Loading…
Reference in new issue