Refactor UI components for improved styling and user experience
- Updated UserMenu.vue to enhance button and avatar styles for a more modern look. - Adjusted alert component styles in index.ts for consistent rounded corners. - Simplified loading state markup in order confirmation page for cleaner code. - Enhanced button and link text for better clarity and user navigation. These changes aim to improve the overall aesthetic and usability of the application, ensuring a more cohesive user experience.
This commit is contained in:
@@ -44,24 +44,24 @@ async function handleLogout() {
|
|||||||
<template>
|
<template>
|
||||||
<!-- Not logged in: Show login prompt -->
|
<!-- Not logged in: Show login prompt -->
|
||||||
<NuxtLink v-if="!loggedIn" to="/auth"
|
<NuxtLink v-if="!loggedIn" to="/auth"
|
||||||
class="flex items-center gap-2 px-4 py-2 rounded-2xl border-2 border-dashed border-muted-foreground/30 hover:border-experimenta-accent hover:bg-experimenta-accent/10 transition-all"
|
class="flex items-center gap-2 px-4 py-2 rounded-[35px] border-2 border-dashed border-muted-foreground/30 hover:border-experimenta-accent hover:bg-experimenta-accent/10 transition-all"
|
||||||
aria-label="Anmelden oder Registrieren">
|
aria-label="Anmelden oder Registrieren">
|
||||||
<Avatar class="h-10 w-10 border-2 border-muted-foreground/30 rounded-2xl">
|
<Avatar class="h-10 w-10 border-2 border-muted-foreground/30 rounded-2xl">
|
||||||
<AvatarFallback class="bg-muted text-muted-foreground rounded-2xl">
|
<AvatarFallback class="bg-muted text-muted-foreground rounded-2xl">
|
||||||
<User class="h-5 w-5" />
|
<User class="h-5 w-5" />
|
||||||
</AvatarFallback>
|
</AvatarFallback>
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<span class="text-sm font-medium hidden sm:inline">Anmelden</span>
|
<span class="font-medium hidden sm:inline">Anmelden</span>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
|
|
||||||
<!-- Logged in: Show user menu -->
|
<!-- Logged in: Show user menu -->
|
||||||
<DropdownMenu v-else>
|
<DropdownMenu v-else>
|
||||||
<DropdownMenuTrigger as-child>
|
<DropdownMenuTrigger as-child>
|
||||||
<button
|
<button
|
||||||
class="flex items-center gap-3 rounded-2xl px-2 py-1.5 focus:outline-none focus:ring-2 focus:ring-experimenta-accent focus:ring-offset-2 transition-all hover:bg-white/10"
|
class="flex items-center gap-3 rounded-[35px] px-2 py-1.5 focus:outline-none focus:ring-2 focus:ring-experimenta-accent focus:ring-offset-2 transition-all hover:bg-white/10"
|
||||||
aria-label="Benutzermenü öffnen">
|
aria-label="Benutzermenü öffnen">
|
||||||
<!-- Greeting text (Desktop only) -->
|
<!-- Greeting text (Desktop only) -->
|
||||||
<span class="hidden md:inline font-medium text-white">
|
<span class="hidden md:inline font-medium text-white pl-2">
|
||||||
Hallo, {{ user?.firstName }}
|
Hallo, {{ user?.firstName }}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
|||||||
@@ -6,15 +6,14 @@ export { default as AlertDescription } from './AlertDescription.vue'
|
|||||||
export { default as AlertTitle } from './AlertTitle.vue'
|
export { default as AlertTitle } from './AlertTitle.vue'
|
||||||
|
|
||||||
export const alertVariants = cva(
|
export const alertVariants = cva(
|
||||||
'relative w-full rounded-lg border p-4 flex items-center gap-3 [&>svg]:shrink-0 [&>svg]:text-foreground',
|
'relative w-full rounded-[25px] border p-4 flex items-center gap-3 [&>svg]:shrink-0 [&>svg]:text-foreground',
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default: 'bg-background text-foreground',
|
default: 'bg-background text-foreground',
|
||||||
destructive:
|
destructive:
|
||||||
'border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive',
|
'border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive',
|
||||||
error:
|
error: 'bg-white/15 border-l-4 border-warning text-white [&>svg]:text-warning',
|
||||||
'bg-white/15 border-l-4 border-warning text-white [&>svg]:text-warning',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
|
|||||||
@@ -119,9 +119,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
<!-- Loading State -->
|
<!-- Loading State -->
|
||||||
<div v-if="isLoading" class="text-center py-12">
|
<div v-if="isLoading" class="text-center py-12">
|
||||||
<div
|
<div class="animate-spin rounded-full h-12 w-12 border-4 border-white/20 border-t-white mx-auto mb-4" />
|
||||||
class="animate-spin rounded-full h-12 w-12 border-4 border-white/20 border-t-white mx-auto mb-4"
|
|
||||||
/>
|
|
||||||
<p class="text-white/60">Lade Bestellung...</p>
|
<p class="text-white/60">Lade Bestellung...</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -135,19 +133,11 @@ onMounted(() => {
|
|||||||
<!-- Warning Notice -->
|
<!-- Warning Notice -->
|
||||||
<Alert class="border-yellow-500/50 bg-yellow-500/10">
|
<Alert class="border-yellow-500/50 bg-yellow-500/10">
|
||||||
<div class="flex items-start gap-3">
|
<div class="flex items-start gap-3">
|
||||||
<svg
|
<svg class="w-5 h-5 text-yellow-500 mt-0.5 flex-shrink-0" fill="none" stroke="currentColor"
|
||||||
class="w-5 h-5 text-yellow-500 mt-0.5 flex-shrink-0"
|
viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
fill="none"
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
stroke="currentColor"
|
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z">
|
||||||
viewBox="0 0 24 24"
|
</path>
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="2"
|
|
||||||
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
|
|
||||||
></path>
|
|
||||||
</svg>
|
</svg>
|
||||||
<div>
|
<div>
|
||||||
<AlertTitle class="text-yellow-500">Wichtiger Hinweis</AlertTitle>
|
<AlertTitle class="text-yellow-500">Wichtiger Hinweis</AlertTitle>
|
||||||
@@ -162,34 +152,18 @@ onMounted(() => {
|
|||||||
<!-- Confirmation Button -->
|
<!-- Confirmation Button -->
|
||||||
<Card class="p-6">
|
<Card class="p-6">
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<Button
|
<Button @click="confirmOrder" :disabled="isConfirming" variant="experimenta" size="experimenta"
|
||||||
@click="confirmOrder"
|
class="w-full">
|
||||||
:disabled="isConfirming"
|
|
||||||
variant="experimenta"
|
|
||||||
size="experimenta"
|
|
||||||
class="w-full"
|
|
||||||
>
|
|
||||||
<span v-if="!isConfirming" class="flex items-center justify-center gap-2">
|
<span v-if="!isConfirming" class="flex items-center justify-center gap-2">
|
||||||
<svg
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"
|
||||||
class="w-5 h-5"
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
fill="none"
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
stroke="currentColor"
|
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||||
viewBox="0 0 24 24"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="2"
|
|
||||||
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
||||||
></path>
|
|
||||||
</svg>
|
</svg>
|
||||||
<span>Jetzt verbindlich bestellen</span>
|
<span>Jetzt verbindlich bestellen</span>
|
||||||
</span>
|
</span>
|
||||||
<span v-else class="flex items-center gap-2">
|
<span v-else class="flex items-center gap-2">
|
||||||
<div
|
<div class="animate-spin rounded-full h-4 w-4 border-2 border-white/20 border-t-white" />
|
||||||
class="animate-spin rounded-full h-4 w-4 border-2 border-white/20 border-t-white"
|
|
||||||
/>
|
|
||||||
Bestätigung läuft...
|
Bestätigung läuft...
|
||||||
</span>
|
</span>
|
||||||
</Button>
|
</Button>
|
||||||
@@ -210,8 +184,8 @@ onMounted(() => {
|
|||||||
|
|
||||||
<!-- Back Link -->
|
<!-- Back Link -->
|
||||||
<div class="text-center pt-4">
|
<div class="text-center pt-4">
|
||||||
<NuxtLink to="/checkout" class="text-sm text-experimenta-accent hover:underline">
|
<NuxtLink to="/warenkorb" class="text-sm text-experimenta-accent hover:underline">
|
||||||
← Zurück zur Kasse
|
← Zurück zum Warenkorb
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export default defineEventHandler((event) => {
|
|||||||
|
|
||||||
// Define rate limits per endpoint
|
// Define rate limits per endpoint
|
||||||
const limits: Record<string, { maxAttempts: number; windowMs: number }> = {
|
const limits: Record<string, { maxAttempts: number; windowMs: number }> = {
|
||||||
'/api/auth/login': { maxAttempts: 5, windowMs: 15 * 60 * 1000 }, // 5 per 15min
|
'/api/auth/login': { maxAttempts: 10, windowMs: 10 * 60 * 1000 }, // 10 per 10min
|
||||||
'/api/auth/register': { maxAttempts: 3, windowMs: 60 * 60 * 1000 }, // 3 per hour
|
'/api/auth/register': { maxAttempts: 3, windowMs: 60 * 60 * 1000 }, // 3 per hour
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user