import { useState, useEffect } from 'react' import { useNavigate, Link } from 'react-router-dom' import { useTranslation } from 'react-i18next' import Navbar from '../components/Navbar' import Footer from '../components/Footer' import DynamicPageRenderer from '../components/DynamicPageRenderer' import { API_BASE, type Category, type PageSection } from '../types' 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 { i18n } = useTranslation() 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('') const [loading, setLoading] = useState(false) const [error, setError] = useState(null) const [cmsSections, setCmsSections] = useState([]) useEffect(() => { fetch(`${API_BASE}/pages/track-order-layout`) .then((r) => { if (!r.ok) throw new Error('Page not found'); return r.json(); }) .then((data) => { if (data && data.sections) { setCmsSections(data.sections); } }) .catch((err) => { console.log('Track Order dynamic layout sections not loaded:', err.message); }); }, []) useEffect(() => { fetch(`${API_BASE}/categories?lang=${i18n.language}`) .then(res => res.json()) .then(setCategories) .catch(console.error) 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, i18n.language]) const handleTrackForm = async (e: React.FormEvent) => { e.preventDefault() setLoading(true) setError(null) try { const res = await fetch(`${API_BASE}/orders/track`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ orderId: parseInt(orderId.replace(/[^0-9]/g, ''), 10) || 0, phone }) }) const data = await res.json() if (res.ok && data.success) { // Automatically save to local history so they don't have to type it again if (!localOrders.includes(data.orderId)) { const newOrders = [data.orderId, ...localOrders] setLocalOrders(newOrders) localStorage.setItem('homaroma_local_orders', JSON.stringify(newOrders)) } navigate(`/order/${data.orderId}`) } else { setError(data.error || 'Failed to authenticate order details.') } } catch (err) { console.error(err) setError('An error occurred. Please check your internet connection.') } finally { setLoading(false) } } const announcementSections = cmsSections.filter(s => s.isActive && s.type.toUpperCase() === 'ANNOUNCEMENT_BAR'); const heroSections = cmsSections.filter(s => s.isActive && (s.type.toUpperCase() === 'HERO' || s.type.toUpperCase() === 'BANNER')); const bottomSections = cmsSections.filter(s => s.isActive && s.type.toUpperCase() !== 'ANNOUNCEMENT_BAR' && s.type.toUpperCase() !== 'HERO' && s.type.toUpperCase() !== 'BANNER'); return (
{announcementSections.length > 0 && ( )}
{/* Header */} {heroSections.length > 0 ? ( ) : (

Track Your Status

Enter your order details below to check shipping status or upload payment slips.

)}
{/* Tracking Form */}

Manual Search

{error && (
{error}
)}
setOrderId(e.target.value)} className="w-full bg-spa-light border border-spa-stone/20 rounded-lg p-3.5 text-pop-black focus:border-spa-forest focus:ring-1 focus:ring-spa-forest outline-none transition-all placeholder:text-spa-stone/50" placeholder="e.g. 1024" />
setPhone(e.target.value)} className="w-full bg-spa-light border border-spa-stone/20 rounded-lg p-3.5 text-pop-black focus:border-spa-forest focus:ring-1 focus:ring-spa-forest outline-none transition-all placeholder:text-spa-stone/50" placeholder="The phone number used during checkout" />
{/* Local / Account Order History */}

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

{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.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')}

))}
) )}
{bottomSections.length > 0 && ( )}
) }