134 lines
4.3 KiB
TypeScript
134 lines
4.3 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 { useCentralProductStore } from '../lib/stores/central-product-store'
|
|
import { trpc } from '../lib/trpc-client'
|
|
import { clearLocalCart } from '../hooks/cart-query-hooks'
|
|
import { p, MyButton, LoadingDialog, AppContainer, div } from 'web-components'
|
|
import { useQueryClient } from '@tanstack/react-query'
|
|
|
|
export const Route = createFileRoute('/home/checkout')({ component: CheckoutPage })
|
|
|
|
function CheckoutPage() {
|
|
const navigate = useNavigate()
|
|
const queryClient = useQueryClient()
|
|
const { isAuthenticated } = useAuth()
|
|
const { data: cart } = useGetCart('regular')
|
|
const productsById = useCentralProductStore((s) => s.productsById)
|
|
const [isLoading, setIsLoading] = useState(false)
|
|
|
|
const { data: addresses } = trpc.user.address.getUserAddresses.useQuery(undefined, {
|
|
enabled: isAuthenticated,
|
|
})
|
|
const [selectedAddressId, setSelectedAddressId] = useState<number | null>(null)
|
|
|
|
const placeOrderMutation = trpc.user.order.placeOrder.useMutation({
|
|
onSuccess: (data) => {
|
|
const order = data.data?.[0]
|
|
clearLocalCart('regular')
|
|
queryClient.invalidateQueries({ queryKey: ['local-cart-regular'] })
|
|
navigate({
|
|
to: '/home/order-success',
|
|
search: { orderId: order?.id, totalAmount: total },
|
|
})
|
|
},
|
|
onSettled: () => setIsLoading(false),
|
|
})
|
|
|
|
const cartItems = (cart?.items || []).filter((item) => productsById[item.productId])
|
|
|
|
let total = 0
|
|
cartItems.forEach((item) => {
|
|
const product = productsById[item.productId]
|
|
if (product) {
|
|
total += (product.discountedPrice ?? product.price) * item.quantity
|
|
}
|
|
})
|
|
|
|
const handlePlaceOrder = () => {
|
|
if (!selectedAddressId) return
|
|
setIsLoading(true)
|
|
placeOrderMutation.mutate({
|
|
selectedItems: cartItems.map((item) => ({
|
|
productId: item.productId,
|
|
quantity: item.quantity,
|
|
slotId: null,
|
|
})),
|
|
addressId: selectedAddressId,
|
|
paymentMethod: 'cod',
|
|
isFlashDelivery: false,
|
|
})
|
|
}
|
|
|
|
return (
|
|
<AppContainer>
|
|
<p className="font-bold mb-4 text-xl">
|
|
Checkout
|
|
</p>
|
|
|
|
{/* Address Selection */}
|
|
<div className="mb-6">
|
|
<p className="font-semibold mb-2">
|
|
Delivery Address
|
|
</p>
|
|
{addresses?.data?.map((addr: any) => (
|
|
<div
|
|
key={addr.id}
|
|
onClick={() => setSelectedAddressId(addr.id)}
|
|
className={`mb-2 rounded-xl border p-3 ${
|
|
selectedAddressId === addr.id
|
|
? 'border-brand-500 bg-brand-50'
|
|
: 'border-gray-200'
|
|
}`}
|
|
>
|
|
<p className="font-semibold">{addr.name}</p>
|
|
<p className="text-sm text-gray-600">
|
|
{addr.addressLine1}, {addr.city}
|
|
</p>
|
|
<p className="text-sm text-gray-500">{addr.phone}</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{/* Order Summary */}
|
|
<div className="mb-6">
|
|
<p className="font-semibold mb-2">
|
|
Order Summary
|
|
</p>
|
|
{cartItems.map((item) => {
|
|
const product = productsById[item.productId]
|
|
if (!product) return null
|
|
return (
|
|
<div key={item.productId} className="flex items-center justify-between py-2">
|
|
<p className="text-sm">
|
|
{product.name} x{item.quantity}
|
|
</p>
|
|
<p className="text-sm font-bold">
|
|
₹{(product.discountedPrice ?? product.price) * item.quantity}
|
|
</p>
|
|
</div>
|
|
)
|
|
})}
|
|
<div className="mt-2 border-t border-gray-200 pt-2">
|
|
<div className="flex items-center justify-between">
|
|
<p className="font-bold">Total</p>
|
|
<p className="font-bold text-brand-600">
|
|
₹{total}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<MyButton
|
|
fullWidth
|
|
textContent="Place Order (COD)"
|
|
onClick={handlePlaceOrder}
|
|
disabled={!selectedAddressId || placeOrderMutation.isPending}
|
|
className="bg-brand-500 text-white"
|
|
/>
|
|
|
|
<LoadingDialog open={isLoading} message="Placing your order..." />
|
|
</AppContainer>
|
|
)
|
|
}
|