Rocky_Mountain_Vending/app/api/orders/route.ts

166 lines
4.2 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server'
import { requireAdminToken } from '@/lib/server/admin-auth'
// Order types
interface OrderItem {
productId: string
productName: string
price: number
quantity: number
priceId: string
}
interface Order {
id: string
customerId: string | null
customerEmail: string
items: OrderItem[]
totalAmount: number
currency: string
status: 'pending' | 'paid' | 'fulfilled' | 'cancelled' | 'refunded'
paymentIntentId: string | null
stripeSessionId: string | null
createdAt: string
updatedAt: string
shippingAddress?: {
name: string
address: string
city: string
state: string
zipCode: string
country: string
}
}
// In-memory storage for demo purposes
// In a real application, you would use a database
let orders: Order[] = []
// Generate a simple ID for demo
function generateOrderId(): string {
return 'ORD-' + Date.now() + '-' + Math.floor(Math.random() * 1000)
}
export async function GET(request: NextRequest) {
const authError = requireAdminToken(request)
if (authError) {
return authError
}
try {
const { searchParams } = new URL(request.url)
const page = parseInt(searchParams.get('page') || '1')
const limit = parseInt(searchParams.get('limit') || '10')
const status = searchParams.get('status') || undefined
const customerEmail = searchParams.get('customerEmail') || undefined
// Filter orders
let filteredOrders = [...orders]
if (status) {
filteredOrders = filteredOrders.filter(order => order.status === status)
}
if (customerEmail) {
filteredOrders = filteredOrders.filter(order =>
order.customerEmail.toLowerCase().includes(customerEmail.toLowerCase())
)
}
// Sort by creation date (newest first)
filteredOrders.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime())
// Pagination
const startIndex = (page - 1) * limit
const endIndex = startIndex + limit
const paginatedOrders = filteredOrders.slice(startIndex, endIndex)
return NextResponse.json({
orders: paginatedOrders,
pagination: {
page,
limit,
total: filteredOrders.length,
totalPages: Math.ceil(filteredOrders.length / limit)
}
})
} catch (error) {
console.error('Error fetching orders:', error)
return NextResponse.json(
{ error: 'Failed to fetch orders' },
{ status: 500 }
)
}
}
export async function POST(request: NextRequest) {
const authError = requireAdminToken(request)
if (authError) {
return authError
}
try {
const body = await request.json()
const { items, customerEmail, paymentIntentId, stripeSessionId, shippingAddress } = body
// Validate required fields
if (!items || !Array.isArray(items) || items.length === 0) {
return NextResponse.json(
{ error: 'Items are required' },
{ status: 400 }
)
}
if (!customerEmail) {
return NextResponse.json(
{ error: 'Customer email is required' },
{ status: 400 }
)
}
if (!paymentIntentId) {
return NextResponse.json(
{ error: 'Payment intent ID is required' },
{ status: 400 }
)
}
if (!stripeSessionId) {
return NextResponse.json(
{ error: 'Stripe session ID is required' },
{ status: 400 }
)
}
// Calculate total
const totalAmount = items.reduce((total: number, item: OrderItem) => {
return total + (item.price * item.quantity)
}, 0)
// Create order
const newOrder: Order = {
id: generateOrderId(),
customerId: null, // TODO: Implement customer accounts
customerEmail,
items,
totalAmount,
currency: 'usd',
status: 'paid', // Assume payment was successful since webhook was triggered
paymentIntentId,
stripeSessionId,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
shippingAddress
}
orders.unshift(newOrder) // Add to beginning of array
return NextResponse.json(newOrder, { status: 201 })
} catch (error) {
console.error('Error creating order:', error)
return NextResponse.json(
{ error: 'Failed to create order' },
{ status: 500 }
)
}
}