← back to IWasCute

src/app/browse/page.tsx

282 lines

'use client'

import { useState } from 'react'
import { motion, AnimatePresence } from 'framer-motion'
import {
  Search,
  SlidersHorizontal,
  Grid3X3,
  LayoutList,
  ShieldCheck,
  ChevronDown,
  ImageIcon,
  Tag,
  Calendar,
} from 'lucide-react'
import Navbar from '@/components/shared/Navbar'

type ViewMode = 'grid' | 'list'
type LicenseFilter = 'all' | 'editorial' | 'commercial' | 'ai-training'

const LICENSE_FILTERS: { id: LicenseFilter; label: string }[] = [
  { id: 'all', label: 'All' },
  { id: 'editorial', label: 'Editorial' },
  { id: 'commercial', label: 'Commercial' },
  { id: 'ai-training', label: 'AI Training' },
]

// Placeholder categories for when photos are available
const CATEGORIES = [
  'All Photos',
  'Baby & Toddler',
  'School Age',
  'Teenager',
  'Family',
  'Holidays',
  'Outdoor',
  'Portraits',
]

function SearchBar({
  value,
  onChange,
}: {
  value: string
  onChange: (v: string) => void
}) {
  return (
    <div className="relative flex-1">
      <Search
        size={16}
        className="absolute left-4 top-1/2 -translate-y-1/2 pointer-events-none"
        style={{ color: 'var(--color-warm-gray)' }}
      />
      <input
        type="text"
        value={value}
        onChange={(e) => onChange(e.target.value)}
        placeholder="Search photos by keyword, era, or description..."
        className="w-full pl-11 pr-4 py-3 rounded-2xl text-sm border outline-none transition-all focus:ring-2"
        style={{
          background: 'rgba(255,255,255,0.8)',
          borderColor: 'var(--color-cream-dark)',
          color: 'var(--color-brown)',
        }}
      />
    </div>
  )
}

function EmptyMarketplace() {
  return (
    <div
      className="flex flex-col items-center justify-center gap-8 py-24 text-center"
    >
      {/* Decorative placeholder grid */}
      <div className="grid grid-cols-3 gap-3 opacity-30">
        {Array.from({ length: 9 }).map((_, i) => (
          <div
            key={i}
            className="w-24 h-24 md:w-32 md:h-32 rounded-2xl flex items-center justify-center"
            style={{ background: 'var(--color-cream-dark)' }}
          >
            <ImageIcon size={24} style={{ color: 'var(--color-warm-gray)' }} />
          </div>
        ))}
      </div>

      <div className="max-w-md">
        <h2 className="text-2xl font-black tracking-tighter" style={{ color: 'var(--color-brown)' }}>
          The marketplace is coming soon
        </h2>
        <p className="mt-3 text-base leading-relaxed" style={{ color: 'var(--color-warm-gray)' }}>
          Photos are being uploaded and reviewed. The first rights-cleared childhood photos
          will appear here shortly. Every photo has both copyright and likeness rights verified.
        </p>
      </div>

      {/* Trust badges */}
      <div className="flex flex-wrap justify-center gap-4 mt-4">
        {[
          { icon: ShieldCheck, label: 'Dual-rights verified' },
          { icon: Tag, label: 'Clear licensing tiers' },
          { icon: Calendar, label: 'AI training available' },
        ].map(({ icon: Icon, label }) => (
          <div
            key={label}
            className="flex items-center gap-2 px-4 py-2.5 rounded-2xl"
            style={{ background: 'rgba(181, 213, 197, 0.2)', border: '1px solid var(--color-sage)' }}
          >
            <Icon size={14} style={{ color: 'var(--color-sage-dark)' }} />
            <span className="text-xs font-semibold" style={{ color: 'var(--color-sage-dark)' }}>
              {label}
            </span>
          </div>
        ))}
      </div>
    </div>
  )
}

export default function BrowsePage() {
  const [search, setSearch] = useState('')
  const [viewMode, setViewMode] = useState<ViewMode>('grid')
  const [licenseFilter, setLicenseFilter] = useState<LicenseFilter>('all')
  const [activeCategory, setActiveCategory] = useState('All Photos')
  const [showFilters, setShowFilters] = useState(false)

  // No photos yet — marketplace is pre-launch
  const photos: unknown[] = []

  return (
    <div className="min-h-screen" style={{ background: 'var(--color-cream)' }}>
      <Navbar />

      <div className="max-w-6xl mx-auto px-4 py-8 md:px-8 md:py-12">
        {/* Header */}
        <div className="mb-8">
          <h1 className="text-3xl font-black tracking-tighter" style={{ color: 'var(--color-brown)' }}>
            Browse Photos
          </h1>
          <p className="mt-1 text-sm" style={{ color: 'var(--color-warm-gray)' }}>
            Every photo is dual-rights cleared — copyright and likeness verified.
          </p>
        </div>

        {/* Search + controls */}
        <div className="flex flex-col gap-4 mb-6">
          <div className="flex gap-3">
            <SearchBar value={search} onChange={setSearch} />

            <button
              onClick={() => setShowFilters(!showFilters)}
              className="flex items-center gap-2 px-4 py-3 rounded-2xl text-sm font-medium border transition-all hover:scale-105"
              style={{
                background: showFilters ? 'var(--color-peach)' : 'rgba(255,255,255,0.8)',
                borderColor: showFilters ? 'var(--color-peach)' : 'var(--color-cream-dark)',
                color: showFilters ? 'var(--color-brown)' : 'var(--color-warm-gray)',
              }}
            >
              <SlidersHorizontal size={14} />
              Filters
              <ChevronDown
                size={12}
                className="transition-transform"
                style={{ transform: showFilters ? 'rotate(180deg)' : 'none' }}
              />
            </button>

            {/* View toggle */}
            <div
              className="flex rounded-2xl border overflow-hidden"
              style={{ borderColor: 'var(--color-cream-dark)' }}
            >
              <button
                onClick={() => setViewMode('grid')}
                className="px-3 py-3 transition-all"
                style={{
                  background: viewMode === 'grid' ? 'var(--color-cream-dark)' : 'rgba(255,255,255,0.8)',
                  color: 'var(--color-warm-gray)',
                }}
                aria-label="Grid view"
              >
                <Grid3X3 size={16} />
              </button>
              <button
                onClick={() => setViewMode('list')}
                className="px-3 py-3 transition-all"
                style={{
                  background: viewMode === 'list' ? 'var(--color-cream-dark)' : 'rgba(255,255,255,0.8)',
                  color: 'var(--color-warm-gray)',
                }}
                aria-label="List view"
              >
                <LayoutList size={16} />
              </button>
            </div>
          </div>

          {/* Filter panel */}
          <AnimatePresence>
            {showFilters && (
              <motion.div
                initial={{ opacity: 0, height: 0 }}
                animate={{ opacity: 1, height: 'auto' }}
                exit={{ opacity: 0, height: 0 }}
                transition={{ duration: 0.2 }}
                className="overflow-hidden"
              >
                <div
                  className="p-5 rounded-2xl flex flex-col gap-4"
                  style={{ background: 'rgba(255,255,255,0.6)', border: '1px solid var(--color-cream-dark)' }}
                >
                  {/* License type */}
                  <div>
                    <p className="text-xs font-bold tracking-widest uppercase mb-2" style={{ color: 'var(--color-warm-gray)' }}>
                      License Type
                    </p>
                    <div className="flex gap-2 flex-wrap">
                      {LICENSE_FILTERS.map((f) => (
                        <button
                          key={f.id}
                          onClick={() => setLicenseFilter(f.id)}
                          className="px-3.5 py-1.5 rounded-xl text-xs font-semibold transition-all hover:scale-105"
                          style={{
                            background: licenseFilter === f.id ? 'var(--color-peach)' : 'var(--color-cream-dark)',
                            color: licenseFilter === f.id ? 'var(--color-brown)' : 'var(--color-warm-gray)',
                          }}
                        >
                          {f.label}
                        </button>
                      ))}
                    </div>
                  </div>

                  {/* Category chips */}
                  <div>
                    <p className="text-xs font-bold tracking-widest uppercase mb-2" style={{ color: 'var(--color-warm-gray)' }}>
                      Category
                    </p>
                    <div className="flex gap-2 flex-wrap">
                      {CATEGORIES.map((cat) => (
                        <button
                          key={cat}
                          onClick={() => setActiveCategory(cat)}
                          className="px-3.5 py-1.5 rounded-xl text-xs font-semibold transition-all hover:scale-105"
                          style={{
                            background: activeCategory === cat ? 'var(--color-sage)' : 'var(--color-cream-dark)',
                            color: activeCategory === cat ? 'white' : 'var(--color-warm-gray)',
                          }}
                        >
                          {cat}
                        </button>
                      ))}
                    </div>
                  </div>
                </div>
              </motion.div>
            )}
          </AnimatePresence>
        </div>

        {/* Results */}
        {photos.length === 0 ? (
          <EmptyMarketplace />
        ) : (
          <div
            className="grid gap-4"
            style={{
              gridTemplateColumns:
                viewMode === 'grid'
                  ? 'repeat(auto-fill, minmax(220px, 1fr))'
                  : '1fr',
            }}
          >
            {/* Photo cards will render here when marketplace launches */}
          </div>
        )}
      </div>
    </div>
  )
}