diff --git a/apps/backend/src/routes/orders.ts b/apps/backend/src/routes/orders.ts index ff53997..b72981e 100644 --- a/apps/backend/src/routes/orders.ts +++ b/apps/backend/src/routes/orders.ts @@ -123,6 +123,13 @@ export const ordersRoute = new Elysia({ prefix: "/orders" }) paymentSlipUrl: t.String() }) }) + .get("/customer/:customerId", async ({ params: { customerId } }) => { + return await prisma.order.findMany({ + where: { customerId: Number(customerId) }, + orderBy: { createdAt: 'desc' }, + include: { items: true } + }); + }) .post("/track", async ({ body, set }) => { try { const { orderId, phone } = body as any; diff --git a/apps/spa/src/pages/CheckoutPage.tsx b/apps/spa/src/pages/CheckoutPage.tsx index fe306e1..7d80516 100644 --- a/apps/spa/src/pages/CheckoutPage.tsx +++ b/apps/spa/src/pages/CheckoutPage.tsx @@ -31,7 +31,7 @@ export default function CheckoutPage() { address: '' }) - // Prefill form with LINE customer data + // Prefill form with LINE customer data and last used address useEffect(() => { if (customer) { setFormData(prev => ({ @@ -40,6 +40,23 @@ export default function CheckoutPage() { email: prev.email || customer.email || '', phone: prev.phone || customer.phone || '' })) + + // Fetch latest order to pre-fill address acting as an automatic Address Book + fetch(`${API_BASE}/orders/customer/${customer.id}`) + .then(res => res.json()) + .then(data => { + if (Array.isArray(data) && data.length > 0) { + const lastOrder = data[0]; + setFormData(prev => ({ + ...prev, + name: prev.name || lastOrder.customerName || '', + phone: prev.phone || lastOrder.customerPhone || '', + email: prev.email || lastOrder.customerEmail || '', + address: prev.address || lastOrder.shippingAddress || '' + })) + } + }) + .catch(console.error) } }, [customer]) diff --git a/apps/spa/src/pages/TrackOrderPage.tsx b/apps/spa/src/pages/TrackOrderPage.tsx index 4950866..c0f2c5b 100644 --- a/apps/spa/src/pages/TrackOrderPage.tsx +++ b/apps/spa/src/pages/TrackOrderPage.tsx @@ -3,12 +3,24 @@ import { useNavigate, Link } from 'react-router-dom' import Navbar from '../components/Navbar' import Footer from '../components/Footer' import { API_BASE, type Category } from '../types' -import { Search, MapPin, Package, Loader2, ChevronRight } from 'lucide-react' +import { Search, MapPin, Package, Loader2, ChevronRight, Clock } from 'lucide-react' +import { useAuthStore } from '../store/authStore' + +interface OrderHistoryItem { + id: number + status: string + totalAmount: number + createdAt: string + items: any[] +} export default function TrackOrderPage() { const navigate = useNavigate() + const { customer } = useAuthStore() const [categories, setCategories] = useState([]) const [localOrders, setLocalOrders] = useState([]) + const [historyOrders, setHistoryOrders] = useState([]) + const [historyLoading, setHistoryLoading] = useState(false) const [orderId, setOrderId] = useState('') const [phone, setPhone] = useState('') @@ -21,12 +33,23 @@ export default function TrackOrderPage() { .then(setCategories) .catch(console.error) - // Load local orders - const storedStr = localStorage.getItem('homaroma_local_orders') - if (storedStr) { - setLocalOrders(JSON.parse(storedStr)) + if (customer) { + setHistoryLoading(true) + fetch(`${API_BASE}/orders/customer/${customer.id}`) + .then(res => res.json()) + .then(data => { + if (Array.isArray(data)) setHistoryOrders(data) + }) + .catch(console.error) + .finally(() => setHistoryLoading(false)) + } else { + // Load local orders if not logged in + const storedStr = localStorage.getItem('homaroma_local_orders') + if (storedStr) { + setLocalOrders(JSON.parse(storedStr)) + } } - }, []) + }, [customer]) const handleTrackForm = async (e: React.FormEvent) => { e.preventDefault() @@ -127,35 +150,83 @@ export default function TrackOrderPage() { - {/* Local Order History */} + {/* Local / Account Order History */}

- Recent Device Orders + {customer ? ( + <> My Order History + ) : ( + <> Recent Device Orders + )}

- {localOrders.length === 0 ? ( -
-

No recent orders found on this device.

-

Use manual search if you ordered elsewhere

-
+ {customer ? ( + historyLoading ? ( +
+ ) : historyOrders.length === 0 ? ( +
+

No order history found.

+

Start shopping to see your orders here

+
+ ) : ( +
+ {historyOrders.map((order) => ( + +
+
+

Order

+ + {order.status.replace('_', ' ')} + +
+

#{order.id.toString().padStart(4, '0')}

+

{new Date(order.createdAt).toLocaleDateString()}

+
+
+
+

฿{order.totalAmount.toLocaleString()}

+

{order.items.length} items

+
+
+ +
+
+ + ))} +
+ ) ) : ( -
- {localOrders.map((id) => ( - -
-

Order

-

#{id.toString().padStart(4, '0')}

-
-
- -
- - ))} -
+ localOrders.length === 0 ? ( +
+

No recent orders found on this device.

+

Log in with LINE or use manual search

+
+ ) : ( +
+ {localOrders.map((id) => ( + +
+

Order

+

#{id.toString().padStart(4, '0')}

+
+
+ +
+ + ))} +
+ ) )}