profit-planet-frontend/src/app/shop/vip/page.tsx
2025-10-03 22:47:37 +02:00

503 lines
20 KiB
TypeScript

'use client'
import { useState, useEffect } from 'react'
import { StarIcon } from '@heroicons/react/20/solid'
import { HeartIcon, ShoppingCartIcon } from '@heroicons/react/24/outline'
import { HeartIcon as HeartIconSolid } from '@heroicons/react/24/solid'
import PageLayout from '../../components/PageLayout'
// Collections für die Promo Section
const collections = [
{
name: "Women's",
href: '#',
imageSrc: 'https://tailwindcss.com/plus-assets/img/ecommerce-images/home-page-04-collection-01.jpg',
imageAlt: 'Woman wearing an off-white cotton t-shirt.',
},
{
name: "Men's",
href: '#',
imageSrc: 'https://tailwindcss.com/plus-assets/img/ecommerce-images/home-page-04-collection-02.jpg',
imageAlt: 'Man wearing a charcoal gray cotton t-shirt.',
},
{
name: 'Desk Accessories',
href: '#',
imageSrc: 'https://tailwindcss.com/plus-assets/img/ecommerce-images/home-page-04-collection-03.jpg',
imageAlt: 'Person sitting at a wooden desk with paper note organizer, pencil and tablet.',
},
]
// Featured Products für die Shop-Startseite
const featuredProducts = [
{
id: 101,
name: 'Black Basic Tee',
price: '$32',
href: '#',
imageSrc: 'https://tailwindcss.com/plus-assets/img/ecommerce-images/home-page-03-favorite-01.jpg',
imageAlt: "Model wearing women's black cotton crewneck tee.",
},
{
id: 102,
name: 'Off-White Basic Tee',
price: '$32',
href: '#',
imageSrc: 'https://tailwindcss.com/plus-assets/img/ecommerce-images/home-page-03-favorite-02.jpg',
imageAlt: "Model wearing women's off-white cotton crewneck tee.",
},
{
id: 103,
name: 'Mountains Artwork Tee',
price: '$36',
href: '#',
imageSrc: 'https://tailwindcss.com/plus-assets/img/ecommerce-images/home-page-03-favorite-03.jpg',
imageAlt: "Model wearing women's burgundy red crewneck artwork tee with small white triangle overlapping larger black triangle.",
},
]
// Mock-Produktdaten im Tailwind UI Plus Format
const products = [
{
id: 1,
name: 'Premium Bio-Kaffee Starter Set',
price: '€24.99',
rating: 5,
reviewCount: 142,
imageSrc: 'https://images.unsplash.com/photo-1559056199-641a0ac8b55e?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80',
imageAlt: 'Premium Bio-Kaffee Set mit Bohnen und Filter',
href: '#',
category: 'Getränke',
inStock: true,
},
{
id: 2,
name: 'Nachhaltiger Laptop-Ständer',
price: '€89.99',
rating: 5,
reviewCount: 87,
imageSrc: 'https://images.unsplash.com/photo-1527864550417-7fd91fc51a46?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80',
imageAlt: 'Ergonomischer Laptop-Ständer aus Bambus',
href: '#',
category: 'Technik',
inStock: true,
},
{
id: 3,
name: 'Öko-Sportbekleidung Set',
price: '€149.99',
rating: 5,
reviewCount: 203,
imageSrc: 'https://images.unsplash.com/photo-1506629905607-b5f9a71351e8?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80',
imageAlt: 'Nachhaltige Sportkleidung aus recycelten Materialien',
href: '#',
category: 'Kleidung',
inStock: false,
},
{
id: 4,
name: 'Smart Home Energie-Monitor',
price: '€199.99',
rating: 4,
reviewCount: 156,
imageSrc: 'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80',
imageAlt: 'Smart Home Gerät zur Energieüberwachung',
href: '#',
category: 'Technik',
inStock: true,
},
{
id: 5,
name: 'Bio-Hautpflege Starter-Set',
price: '€79.99',
rating: 4,
reviewCount: 92,
imageSrc: 'https://images.unsplash.com/photo-1556228578-8c89e6adf883?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80',
imageAlt: 'Natürliche Hautpflege Produkte ohne Chemikalien',
href: '#',
category: 'Beauty',
inStock: true,
},
{
id: 6,
name: 'Solarbetriebene Powerbank',
price: '€129.99',
rating: 5,
reviewCount: 78,
imageSrc: 'https://images.unsplash.com/photo-1609091839311-d5365f9ff1c5?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80',
imageAlt: 'Portable Solarenergie Powerbank',
href: '#',
category: 'Technik',
inStock: true,
},
{
id: 7,
name: 'Nachhaltige Trinkflasche',
price: '€25.99',
rating: 4,
reviewCount: 64,
imageSrc: 'https://images.unsplash.com/photo-1523362628745-0c100150b504?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80',
imageAlt: 'Wiederverwendbare Edelstahl Trinkflasche',
href: '#',
category: 'Lifestyle',
inStock: true,
},
{
id: 8,
name: 'Öko-Notizbuch Set',
price: '€19.99',
rating: 5,
reviewCount: 41,
imageSrc: 'https://images.unsplash.com/photo-1544716278-ca5e3f4abd8c?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80',
imageAlt: 'Recyceltes Papier Notizbuch Set',
href: '#',
category: 'Büro',
inStock: true,
},
{
id: 9,
name: 'Bambus Handy-Halterung',
price: '€32.99',
rating: 4,
reviewCount: 24,
imageSrc: 'https://images.unsplash.com/photo-1572635196237-14b3f281503f?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80',
imageAlt: 'Nachhaltige Bambus Handy-Halterung',
href: '#',
category: 'Technik',
inStock: true,
},
]
const stats = [
{ name: 'Total Users', stat: '71,897' },
{ name: 'Gold Members', stat: '68,161' },
{ name: 'Savings as Gold member', stat: '25k €' },
]
function classNames(...classes: (string | undefined | null | boolean)[]): string {
return classes.filter(Boolean).join(' ')
}
export default function ShopPage() {
const [favorites, setFavorites] = useState<number[]>([])
const [isLoading, setIsLoading] = useState(true)
// Load favorites from localStorage on component mount
useEffect(() => {
const savedFavorites = localStorage.getItem('shop-favorites')
if (savedFavorites) {
try {
setFavorites(JSON.parse(savedFavorites))
} catch (error) {
console.error('Error parsing favorites from localStorage:', error)
}
}
setIsLoading(false)
}, [])
// Save favorites to localStorage whenever favorites change
useEffect(() => {
if (!isLoading) {
localStorage.setItem('shop-favorites', JSON.stringify(favorites))
}
}, [favorites, isLoading])
const toggleFavorite = (productId: number) => {
setFavorites(prev => {
const newFavorites = prev.includes(productId)
? prev.filter(id => id !== productId)
: [...prev, productId]
// Show feedback to user
const product = products.find(p => p.id === productId)
if (product) {
if (newFavorites.includes(productId)) {
console.log(`❤️ ${product.name} zu Favoriten hinzugefügt`)
} else {
console.log(`💔 ${product.name} aus Favoriten entfernt`)
}
}
return newFavorites
})
}
const addToCart = (productId: number) => {
const product = products.find(p => p.id === productId)
if (product) {
console.log(`🛒 ${product.name} zum Warenkorb hinzugefügt`)
// Hier würde die echte Add-to-Cart Logik implementiert werden
// z.B. API-Call oder Zustand-Update
}
}
if (isLoading) {
return (
<PageLayout>
<div className="min-h-screen flex items-center justify-center">
<div className="text-center">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-[#8D6B1D] mx-auto mb-4"></div>
<p className="text-[#4A4A4A]">Shop wird geladen...</p>
</div>
</div>
</PageLayout>
)
}
return (
<PageLayout>
<div className="bg-white">
{/* Promo Section with Stats Cards */}
<div className="relative overflow-hidden bg-white">
<div className="pt-16 pb-80 sm:pt-24 sm:pb-40 lg:pt-40 lg:pb-48">
<div className="relative mx-auto max-w-7xl px-4 sm:static sm:px-6 lg:px-8">
<div className="sm:max-w-lg">
{/* Stats Cards */}
{/* <div className="mb-8">
<dl className="grid grid-cols-1 gap-4 sm:grid-cols-3 sm:gap-5">
{stats.map((item) => (
<div
key={item.name}
className="overflow-hidden rounded-lg bg-white px-4 py-5 shadow-lg border border-gray-200 sm:p-6"
>
<dt className="truncate text-sm font-medium text-gray-600">{item.name}</dt>
<dd className="mt-1 text-2xl font-semibold tracking-tight text-gray-900 sm:text-3xl">{item.stat}</dd>
</div>
))}
</dl>
</div> */}
<h1 className="text-4xl font-bold tracking-tight text-gray-900 sm:text-6xl">
Shop with an infinite variety of products
</h1>
<p className="mt-4 text-xl text-gray-500">
Discover a curated selection of high-quality products that cater to your every need.
</p>
</div>
<div>
<div className="mt-10">
{/* Decorative image grid */}
<div
aria-hidden="true"
className="pointer-events-none lg:absolute lg:inset-y-0 lg:mx-auto lg:w-full lg:max-w-7xl"
>
<div className="absolute transform sm:top-0 sm:left-1/2 sm:translate-x-8 lg:top-1/2 lg:left-1/2 lg:translate-x-8 lg:-translate-y-1/2">
<div className="flex items-center space-x-6 lg:space-x-8">
<div className="grid shrink-0 grid-cols-1 gap-y-6 lg:gap-y-8">
<div className="h-64 w-44 overflow-hidden rounded-lg sm:opacity-0 lg:opacity-100">
<img
alt=""
src="https://tailwindcss.com/plus-assets/img/ecommerce-images/home-page-03-hero-image-tile-01.jpg"
className="size-full object-cover"
/>
</div>
<div className="h-64 w-44 overflow-hidden rounded-lg">
<img
alt=""
src="https://tailwindcss.com/plus-assets/img/ecommerce-images/home-page-03-hero-image-tile-02.jpg"
className="size-full object-cover"
/>
</div>
</div>
<div className="grid shrink-0 grid-cols-1 gap-y-6 lg:gap-y-8">
<div className="h-64 w-44 overflow-hidden rounded-lg">
<img
alt=""
src="https://tailwindcss.com/plus-assets/img/ecommerce-images/home-page-03-hero-image-tile-03.jpg"
className="size-full object-cover"
/>
</div>
<div className="h-64 w-44 overflow-hidden rounded-lg">
<img
alt=""
src="https://tailwindcss.com/plus-assets/img/ecommerce-images/home-page-03-hero-image-tile-04.jpg"
className="size-full object-cover"
/>
</div>
<div className="h-64 w-44 overflow-hidden rounded-lg">
<img
alt=""
src="https://tailwindcss.com/plus-assets/img/ecommerce-images/home-page-03-hero-image-tile-05.jpg"
className="size-full object-cover"
/>
</div>
</div>
<div className="grid shrink-0 grid-cols-1 gap-y-6 lg:gap-y-8">
<div className="h-64 w-44 overflow-hidden rounded-lg">
<img
alt=""
src="https://tailwindcss.com/plus-assets/img/ecommerce-images/home-page-03-hero-image-tile-06.jpg"
className="size-full object-cover"
/>
</div>
<div className="h-64 w-44 overflow-hidden rounded-lg">
<img
alt=""
src="https://tailwindcss.com/plus-assets/img/ecommerce-images/home-page-03-hero-image-tile-07.jpg"
className="size-full object-cover"
/>
</div>
</div>
</div>
</div>
</div>
<a
href="#"
className="inline-block rounded-md border border-transparent bg-indigo-600 px-8 py-3 text-center font-medium text-white hover:bg-indigo-700"
>
Shop Collection
</a>
</div>
</div>
</div>
</div>
</div>
{/* Featured Products Section */}
<div className="bg-white">
<div className="mx-auto max-w-7xl px-4 py-16 sm:px-6 sm:py-24 lg:px-8">
<div className="sm:flex sm:items-baseline sm:justify-between">
<h2 className="text-2xl font-bold tracking-tight text-gray-900">Trending right now</h2>
<a href="#" className="hidden text-sm font-semibold text-indigo-600 hover:text-indigo-500 sm:block">
Browse all trending
<span aria-hidden="true"> &rarr;</span>
</a>
</div>
<div className="mt-6 grid grid-cols-1 gap-y-10 sm:grid-cols-3 sm:gap-x-6 sm:gap-y-0 lg:gap-x-8">
{featuredProducts.map((product) => (
<div key={product.id} className="group relative">
<img
alt={product.imageAlt}
src={product.imageSrc}
className="h-96 w-full rounded-lg object-cover group-hover:opacity-75 sm:aspect-2/3 sm:h-auto"
/>
<h3 className="mt-4 text-base font-semibold text-gray-900">
<a href={product.href}>
<span className="absolute inset-0" />
{product.name}
</a>
</h3>
<p className="mt-1 text-sm text-gray-500">{product.price}</p>
</div>
))}
</div>
<div className="mt-6 sm:hidden">
<a href="#" className="block text-sm font-semibold text-indigo-600 hover:text-indigo-500">
Browse all favorites
<span aria-hidden="true"> &rarr;</span>
</a>
</div>
</div>
</div>
{/* Products Section - Tailwind UI Plus "Product Grid" */}
<div className="mx-auto max-w-2xl px-4 py-16 sm:px-6 sm:py-24 lg:max-w-7xl lg:px-8">
<h2 className="sr-only">Products</h2>
<div className="grid grid-cols-1 gap-x-6 gap-y-10 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 xl:gap-x-8">
{products.map((product) => (
<a key={product.id} href={product.href} className="group">
<div className="relative">
{/* Product Image */}
<div className="aspect-h-1 aspect-w-1 w-full overflow-hidden rounded-lg bg-gray-200 xl:aspect-h-8 xl:aspect-w-7">
<img
alt={product.imageAlt}
src={product.imageSrc}
className="h-full w-full object-cover object-center group-hover:opacity-75"
/>
{/* Favorite Button - Now with better positioning */}
<button
onClick={(e) => {
e.preventDefault()
e.stopPropagation()
toggleFavorite(product.id)
}}
className={classNames(
'absolute top-3 right-3 rounded-full bg-white p-2 text-gray-400 shadow-sm hover:bg-gray-50 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-[#8D6B1D]',
'opacity-0 transition-opacity group-hover:opacity-100',
favorites.includes(product.id) ? 'opacity-100 text-red-500 hover:text-red-600' : ''
)}
title={favorites.includes(product.id) ? 'Aus Favoriten entfernen' : 'Zu Favoriten hinzufügen'}
>
{favorites.includes(product.id) ? (
<HeartIconSolid className="h-5 w-5" />
) : (
<HeartIcon className="h-5 w-5" />
)}
</button>
{/* Category Badge */}
<div className="absolute top-3 left-3">
<span className="inline-flex items-center rounded-full bg-[#8D6B1D] px-2 py-1 text-xs font-medium text-white">
{product.category}
</span>
</div>
{/* Out of Stock Overlay */}
{!product.inStock && (
<div className="absolute inset-0 flex items-center justify-center rounded-lg bg-black bg-opacity-50">
<span className="rounded-md bg-white px-3 py-1 text-sm font-semibold text-gray-900">
Ausverkauft
</span>
</div>
)}
</div>
{/* Product Info */}
<div className="mt-4 flex justify-between">
<div>
<h3 className="text-sm text-gray-700">
{product.name}
</h3>
{/* Rating */}
<div className="mt-1 flex items-center">
<div className="flex items-center">
{[0, 1, 2, 3, 4].map((rating) => (
<StarIcon
key={rating}
aria-hidden="true"
className={classNames(
product.rating > rating ? 'text-yellow-400' : 'text-gray-300',
'h-4 w-4 flex-shrink-0'
)}
/>
))}
</div>
<p className="ml-1 text-sm text-gray-500">({product.reviewCount})</p>
</div>
</div>
<p className="text-lg font-medium text-gray-900">{product.price}</p>
</div>
{/* Add to Cart Button */}
<button
onClick={(e) => {
e.preventDefault()
e.stopPropagation()
addToCart(product.id)
}}
disabled={!product.inStock}
className={classNames(
'mt-4 flex w-full items-center justify-center rounded-md border border-transparent px-8 py-2 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-[#8D6B1D] focus:ring-offset-2',
product.inStock
? 'bg-[#8D6B1D] text-white hover:bg-[#7A5E1A]'
: 'bg-gray-100 text-gray-400 cursor-not-allowed'
)}
>
<ShoppingCartIcon className="mr-2 h-4 w-4" />
{product.inStock ? 'In den Warenkorb' : 'Ausverkauft'}
</button>
</div>
</a>
))}
</div>
</div>
</div>
</PageLayout>
)
}