freshyo/apps/web-ui/src/routes/checkout.tsx
2026-08-18 23:12:55 +05:30

138 lines
4.9 KiB
TypeScript

import { createFileRoute, useNavigate } from '@tanstack/react-router'
import { useState } from 'react'
import { useAuth } from '../lib/auth-context'
import { useGetCart } from '../hooks/cart-query-hooks'
import { useAllProducts } from '../hooks/prominent-api-hooks'
import { ProtectedRoute } from '../components/ProtectedRoute'
import { CheckoutAddressSelector } from '../components/CheckoutAddressSelector'
import { PaymentAndOrderComponent } from '../components/PaymentAndOrderComponent'
import { AddressForm } from '../components/AddressForm'
import { Dialog } from '../components/Dialog'
import { useAddressStore } from '../lib/stores/address-store'
import { useQueryClient } from '@tanstack/react-query'
import { ShoppingCart, ChevronLeft, MapPin } from 'lucide-react'
export const Route = createFileRoute('/checkout')({ component: CheckoutPage })
function CheckoutPage() {
return (
<ProtectedRoute>
<CheckoutContent />
</ProtectedRoute>
)
}
function CheckoutContent() {
const navigate = useNavigate()
const queryClient = useQueryClient()
const { isAuthenticated } = useAuth()
const { selectedAddressId, setSelectedAddressId } = useAddressStore()
const [showAddAddress, setShowAddAddress] = useState(false)
const [editingAddress, setEditingAddress] = useState<any>(null)
const cartType: 'regular' | 'flash' = 'regular'
const { data: cartData } = useGetCart(cartType)
const { data: productsData } = useAllProducts()
const products = productsData?.products || []
const productsById: Record<number, any> = {}
products.forEach((p: any) => { productsById[p.id] = p })
const cartItems = (cartData?.items || []).filter((item) => productsById[item.productId])
// Handle empty cart case
if (cartItems.length === 0) {
return (
<div className="flex min-h-screen flex-col items-center justify-center bg-gray-50 p-6">
<div className="flex h-20 w-20 items-center justify-center rounded-2xl bg-white">
<ShoppingCart className="h-9 w-9 text-gray-400" />
</div>
<p className="mt-6 text-xl font-bold text-gray-900">
Your cart is empty
</p>
<p className="mb-6 mt-1 text-gray-500">
Add some delicious items to your cart before checking out
</p>
<button
onClick={() => navigate({ to: '/home' })}
className="rounded-lg bg-brand-600 px-6 py-3 text-sm font-bold text-white transition-colors hover:bg-brand-700"
>
Back to Shopping
</button>
</div>
)
}
return (
<div className="min-h-screen bg-gray-50">
{/* Checkout Header */}
<div className="sticky top-0 z-20 border-b border-gray-200 bg-white">
<div className="mx-auto flex h-16 w-full max-w-7xl items-center gap-3 px-4 md:px-8">
<button
onClick={() => navigate({ to: '/cart' })}
className="flex h-9 w-9 items-center justify-center rounded-lg text-gray-600 transition-colors hover:bg-gray-50"
aria-label="Back to cart"
>
<ChevronLeft className="h-5 w-5" />
</button>
<div className="flex h-9 w-9 items-center justify-center rounded-lg bg-brand-25">
<MapPin className="h-4 w-4 text-brand-600" />
</div>
<p className="font-display text-lg font-extrabold text-gray-900">
Checkout
</p>
</div>
</div>
<div className="mx-auto grid w-full max-w-7xl gap-8 px-4 py-6 md:px-8 lg:grid-cols-[minmax(0,1fr)_420px]">
{/* Left: Address Selection + Payment */}
<div>
<CheckoutAddressSelector
onAddressSelect={setSelectedAddressId}
onAddAddress={() => {
setEditingAddress(null)
setShowAddAddress(true)
}}
onEditAddress={(address) => {
setEditingAddress(address)
setShowAddAddress(true)
}}
/>
</div>
{/* Right: Order summary + payment */}
<div className="lg:sticky lg:top-24 lg:self-start">
<PaymentAndOrderComponent
selectedAddress={selectedAddressId}
cartItems={cartItems}
isFlashDelivery={false}
onBack={() => navigate({ to: '/cart' })}
/>
</div>
</div>
{/* Add/Edit Address Dialog */}
<Dialog
open={showAddAddress}
onClose={() => {
setShowAddAddress(false)
setEditingAddress(null)
}}
title={editingAddress ? 'Edit Address' : 'Add Address'}
>
<AddressForm
onSuccess={(addressId) => {
setShowAddAddress(false)
setEditingAddress(null)
if (addressId) {
setSelectedAddressId(addressId)
}
queryClient.invalidateQueries({ queryKey: ['user.address.getUserAddresses'] })
}}
initialValues={editingAddress || undefined}
isEdit={!!editingAddress}
/>
</Dialog>
</div>
)
}