freshyo/apps/web-ui/src/routes/home.checkout.tsx
2026-05-10 19:44:26 +05:30

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>
)
}