← back to Dear Bubbe Nextjs

app/api/shopify/products/route.ts

196 lines

import { NextRequest, NextResponse } from 'next/server'

// Mock Shopify products data - replace with actual Shopify API integration
const MOCK_PRODUCTS = [
  {
    id: 'prod_001',
    title: 'Elegant Floral Wallcovering',
    handle: 'elegant-floral-wallcovering',
    vendor: 'Designer Collection',
    sku: 'DC-FLR-001',
    imageUrl: 'https://via.placeholder.com/400x400/f093fb/ffffff?text=Floral',
    price: '$89.99',
    description: 'Beautiful floral pattern perfect for dining rooms and living spaces'
  },
  {
    id: 'prod_002', 
    title: 'Modern Geometric Design',
    handle: 'modern-geometric-design',
    vendor: 'Contemporary Line',
    sku: 'CL-GEO-002',
    imageUrl: 'https://via.placeholder.com/400x400/667eea/ffffff?text=Geometric',
    price: '$129.99',
    description: 'Bold geometric patterns for modern interior design'
  },
  {
    id: 'prod_003',
    title: 'Vintage Damask Pattern',
    handle: 'vintage-damask-pattern',
    vendor: 'Classic Designs',
    sku: 'CD-DMS-003',
    imageUrl: 'https://via.placeholder.com/400x400/f5576c/ffffff?text=Damask',
    price: '$156.99',
    description: 'Traditional damask pattern with a vintage aesthetic'
  },
  {
    id: 'prod_004',
    title: 'Tropical Leaf Collection',
    handle: 'tropical-leaf-collection',
    vendor: 'Nature Series',
    sku: 'NS-TRP-004',
    imageUrl: 'https://via.placeholder.com/400x400/48bb78/ffffff?text=Tropical',
    price: '$94.99',
    description: 'Lush tropical leaves bringing nature indoors'
  },
  {
    id: 'prod_005',
    title: 'Abstract Art Wallcovering',
    handle: 'abstract-art-wallcovering',
    vendor: 'Artist Collection',
    sku: 'AC-ABS-005',
    imageUrl: 'https://via.placeholder.com/400x400/fd79a8/ffffff?text=Abstract',
    price: '$198.99',
    description: 'Contemporary abstract design for artistic spaces'
  }
]

interface ShopifyProductsQuery {
  limit?: number
  sortKey?: 'CREATED_AT' | 'UPDATED_AT' | 'TITLE' | 'VENDOR'
  reverse?: boolean
  query?: string
}

// Simulate Shopify GraphQL API response
async function fetchShopifyProducts(queryParams: ShopifyProductsQuery) {
  // In a real implementation, this would make an actual GraphQL call to Shopify
  const { limit = 20, sortKey = 'CREATED_AT', reverse = true, query } = queryParams

  let products = [...MOCK_PRODUCTS]

  // Apply search filter
  if (query) {
    products = products.filter(product => 
      product.title.toLowerCase().includes(query.toLowerCase()) ||
      product.sku.toLowerCase().includes(query.toLowerCase()) ||
      product.vendor.toLowerCase().includes(query.toLowerCase()) ||
      product.description.toLowerCase().includes(query.toLowerCase())
    )
  }

  // Apply sorting
  products.sort((a, b) => {
    let comparison = 0
    switch (sortKey) {
      case 'TITLE':
        comparison = a.title.localeCompare(b.title)
        break
      case 'VENDOR':
        comparison = a.vendor.localeCompare(b.vendor)
        break
      case 'CREATED_AT':
      case 'UPDATED_AT':
      default:
        // Mock timestamp sorting
        comparison = a.id.localeCompare(b.id)
        break
    }
    return reverse ? -comparison : comparison
  })

  // Apply limit
  products = products.slice(0, limit)

  return {
    data: {
      products: {
        edges: products.map(product => ({
          node: product
        }))
      }
    }
  }
}

export async function GET(request: NextRequest) {
  try {
    const { searchParams } = new URL(request.url)
    
    const queryParams: ShopifyProductsQuery = {
      limit: searchParams.get('limit') ? parseInt(searchParams.get('limit')!) : 20,
      sortKey: (searchParams.get('sortKey') as any) || 'CREATED_AT',
      reverse: searchParams.get('reverse') !== 'false',
      query: searchParams.get('query') || undefined
    }

    console.log('[SHOPIFY] Fetching products with params:', queryParams)

    const shopifyResponse = await fetchShopifyProducts(queryParams)

    if (shopifyResponse.data?.products) {
      const products = shopifyResponse.data.products.edges.map((edge: any) => ({
        id: edge.node.id,
        title: edge.node.title,
        handle: edge.node.handle,
        vendor: edge.node.vendor,
        sku: edge.node.sku,
        imageUrl: edge.node.imageUrl,
        price: edge.node.price,
        description: edge.node.description
      }))

      console.log(`[SHOPIFY] Retrieved ${products.length} products`)

      return NextResponse.json({
        products,
        count: products.length,
        query: queryParams.query || null
      })
    } else {
      return NextResponse.json({
        products: [],
        count: 0,
        error: 'No products found'
      })
    }
  } catch (error) {
    console.error('[SHOPIFY] Error fetching products:', error)
    return NextResponse.json({
      error: 'Failed to fetch products from Shopify',
      details: error instanceof Error ? error.message : String(error)
    }, { status: 500 })
  }
}

export async function POST(request: NextRequest) {
  try {
    // This could be used to create new products via GraphQL mutation
    const body = await request.json()
    
    console.log('[SHOPIFY] Create product request:', body)
    
    // Mock successful creation
    const newProduct = {
      id: `prod_${Date.now()}`,
      title: body.title || 'New Product',
      handle: (body.title || 'new-product').toLowerCase().replace(/\s+/g, '-'),
      vendor: body.vendor || 'Default Vendor',
      sku: body.sku || `SKU-${Date.now()}`,
      imageUrl: body.imageUrl || 'https://via.placeholder.com/400x400/cccccc/ffffff?text=New+Product',
      price: body.price || '$0.00',
      description: body.description || 'Product description'
    }
    
    return NextResponse.json({
      success: true,
      product: newProduct,
      message: 'Product created successfully (mock)'
    })
  } catch (error) {
    console.error('[SHOPIFY] Error creating product:', error)
    return NextResponse.json({
      error: 'Failed to create product',
      details: error instanceof Error ? error.message : String(error)
    }, { status: 500 })
  }
}