fix(spa): complete checkout flow, UI standardization, and tailwind v4 styling fixes
This commit is contained in:
1 parent
83df238bab
commit
d8bff72e4e
24 files changed
+1169
-402
No files matched your search
@@ -3,6 +3,7 @@ import { Link, useLocation } from 'react-router-dom'
|
||||
import Navbar from '../components/Navbar'
|
||||
import Footer from '../components/Footer'
|
||||
import ProductCard from '../components/ProductCard'
|
||||
import EmptyState from '../components/EmptyState'
|
||||
import { API_BASE, type Category, type Product } from '../types'
|
||||
|
||||
export default function ShopPage() {
|
||||
@@ -99,19 +100,19 @@ export default function ShopPage() {
|
||||
<Navbar categories={categories} />
|
||||
|
||||
{/* Page Header */}
|
||||
<div className="pt-32 pb-12 px-6 text-center space-y-4 border-b border-white/5 bg-night-800/30">
|
||||
<p className="text-cyan-glow uppercase tracking-[0.4em] text-xs font-semibold opacity-70">
|
||||
<div className="pt-32 pb-12 px-6 text-center space-y-4 border-b border-spa-stone/10 bg-spa-light">
|
||||
<p className="text-spa-forest uppercase tracking-[0.4em] text-xs font-bold opacity-80">
|
||||
All Products
|
||||
</p>
|
||||
<h1 className="text-5xl font-bold tracking-tight">The Collection</h1>
|
||||
<p className="text-slate-400 max-w-md mx-auto">
|
||||
<h1 className="text-5xl font-bold tracking-tight text-pop-black">The Collection</h1>
|
||||
<p className="text-spa-stone max-w-md mx-auto">
|
||||
Browse our full range of premium aroma products — crafted to elevate every space.
|
||||
</p>
|
||||
|
||||
{/* Search */}
|
||||
<div className="max-w-md mx-auto mt-6">
|
||||
<div className="flex glass border border-white/10 rounded-xl overflow-hidden">
|
||||
<svg className="w-4 h-4 text-slate-400 m-3.5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<div className="flex bg-white border border-spa-stone/20 rounded-xl overflow-hidden shadow-sm focus-within:border-spa-forest focus-within:ring-1 focus-within:ring-spa-forest transition-all">
|
||||
<svg className="w-4 h-4 text-spa-stone m-3.5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
||||
</svg>
|
||||
<input
|
||||
@@ -119,7 +120,7 @@ export default function ShopPage() {
|
||||
placeholder="Search by scent or category..."
|
||||
value={searchInput}
|
||||
onChange={(e) => setSearchInput(e.target.value)}
|
||||
className="bg-transparent border-none outline-none text-sm p-2 w-full text-white placeholder-slate-500"
|
||||
className="bg-transparent border-none outline-none text-sm p-2 w-full text-pop-black placeholder-spa-stone/60"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -130,10 +131,10 @@ export default function ShopPage() {
|
||||
<div className="flex flex-wrap gap-3">
|
||||
<button
|
||||
onClick={() => setActiveCategory(null)}
|
||||
className={`px-5 py-2 rounded-full text-xs font-bold uppercase tracking-widest transition-all duration-300 ${
|
||||
className={`px-5 py-2 rounded-full text-xs font-bold uppercase tracking-widest transition-all duration-300 border ${
|
||||
activeCategory === null
|
||||
? 'bg-cyan-glow text-night-900 shadow-[0_0_15px_rgba(102,252,241,0.3)]'
|
||||
: 'glass hover:bg-white/10'
|
||||
? 'bg-spa-forest text-white border-spa-forest shadow-md'
|
||||
: 'bg-white text-spa-stone border-spa-stone/20 hover:border-spa-forest hover:text-spa-forest shadow-sm'
|
||||
}`}
|
||||
>
|
||||
All
|
||||
@@ -142,15 +143,15 @@ export default function ShopPage() {
|
||||
<button
|
||||
key={cat.id}
|
||||
onClick={() => setActiveCategory(cat.id)}
|
||||
className={`px-5 py-2 rounded-full text-xs font-bold uppercase tracking-widest transition-all duration-300 ${
|
||||
className={`px-5 py-2 rounded-full text-xs font-bold uppercase tracking-widest transition-all duration-300 border ${
|
||||
activeCategory === cat.id
|
||||
? 'bg-cyan-glow text-night-900 shadow-[0_0_15px_rgba(102,252,241,0.3)]'
|
||||
: 'glass hover:bg-white/10'
|
||||
? 'bg-spa-forest text-white border-spa-forest shadow-md'
|
||||
: 'bg-white text-spa-stone border-spa-stone/20 hover:border-spa-forest hover:text-spa-forest shadow-sm'
|
||||
}`}
|
||||
>
|
||||
{cat.name}
|
||||
{cat._count && (
|
||||
<span className="ml-2 opacity-60">({cat._count.products})</span>
|
||||
<span className={`ml-2 ${activeCategory === cat.id ? 'opacity-80' : 'opacity-60'}`}>({cat._count.products})</span>
|
||||
)}
|
||||
</button>
|
||||
))}
|
||||
@@ -159,13 +160,13 @@ export default function ShopPage() {
|
||||
{/* Results count */}
|
||||
{(!loading) && (
|
||||
<div className="flex items-center justify-between">
|
||||
<p className="text-slate-500 text-sm">
|
||||
<p className="text-spa-stone font-semibold text-sm">
|
||||
{productsLoading ? 'Loading...' : `${totalProducts} products`}
|
||||
</p>
|
||||
{activeCategory && (
|
||||
<Link
|
||||
to={`/category/${activeCategory}`}
|
||||
className="text-cyan-glow text-xs font-bold uppercase tracking-widest hover:underline"
|
||||
className="text-spa-forest text-xs font-bold uppercase tracking-widest hover:underline"
|
||||
>
|
||||
View Category Page →
|
||||
</Link>
|
||||
@@ -177,15 +178,20 @@ export default function ShopPage() {
|
||||
{loading || productsLoading ? (
|
||||
<div className="grid grid-cols-2 md:grid-cols-3 gap-4 md:gap-8">
|
||||
{Array.from({ length: 9 }).map((_, i) => (
|
||||
<div key={i} className="rounded-2xl bg-white/5 animate-pulse h-96" />
|
||||
<div key={i} className="rounded-2xl bg-spa-stone/10 animate-pulse h-96" />
|
||||
))}
|
||||
</div>
|
||||
) : products.length === 0 ? (
|
||||
<div className="text-center py-24 text-slate-500 space-y-3">
|
||||
<p className="text-4xl">🌿</p>
|
||||
<p className="text-lg">No products found</p>
|
||||
<p className="text-sm">Try adjusting your search or filter</p>
|
||||
</div>
|
||||
<EmptyState
|
||||
title="No products found"
|
||||
message="Try adjusting your search or filter"
|
||||
actionText="Clear Filters"
|
||||
actionClick={() => {
|
||||
setActiveCategory(null);
|
||||
setSearchInput('');
|
||||
setSearchQuery('');
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<div>
|
||||
<div className="grid grid-cols-2 md:grid-cols-3 gap-4 md:gap-8">
|
||||
@@ -197,7 +203,7 @@ export default function ShopPage() {
|
||||
{/* Invisible target for IntersectionObserver */}
|
||||
{displayCount < products.length && (
|
||||
<div ref={loaderRef} className="py-12 flex justify-center">
|
||||
<div className="w-8 h-8 rounded-full border-2 border-cyan-glow border-t-transparent animate-spin" />
|
||||
<div className="w-8 h-8 rounded-full border-2 border-spa-forest border-t-transparent animate-spin" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user