import { useState, useEffect } from 'react' import { Link } from 'react-router-dom' import { useTranslation } from 'react-i18next' import Navbar from '../components/Navbar' import Footer from '../components/Footer' import { API_BASE, formatPrice, type Category, type Order, type CustomerAddress } from '../types' import { useAuthStore } from '../store/authStore' import { User, MapPin, Package, Settings, Plus, Edit3, Trash2, Check, Loader2, ExternalLink, Phone, Mail, Award } from 'lucide-react' import { ThaiAddressInput } from '../components/ui/ThaiAddressInput' export default function ProfilePage() { const { token, customer, setAuth } = useAuthStore() const { i18n } = useTranslation() const [categories, setCategories] = useState([]) // Tab State const [activeTab, setActiveTab] = useState<'orders' | 'addresses' | 'settings'>('orders') // Data States const [dbCustomer, setDbCustomer] = useState(null) const [orders, setOrders] = useState([]) const [addresses, setAddresses] = useState([]) // Loading States const [loadingOrders, setLoadingOrders] = useState(false) const [loadingAddresses, setLoadingAddresses] = useState(false) // Address Form States const [showAddressForm, setShowAddressForm] = useState(false) const [editingAddress, setEditingAddress] = useState(null) const [recipientName, setRecipientName] = useState('') const [phone, setPhone] = useState('') const [addressLine, setAddressLine] = useState('') const [subdistrict, setSubdistrict] = useState('') const [district, setDistrict] = useState('') const [province, setProvince] = useState('') const [zipcode, setZipcode] = useState('') const [isDefault, setIsDefault] = useState(false) const [submittingAddress, setSubmittingAddress] = useState(false) // Settings Form States const [emailInput, setEmailInput] = useState('') const [phoneInput, setPhoneInput] = useState('') const [submittingSettings, setSubmittingSettings] = useState(false) const [settingsSuccess, setSettingsSuccess] = useState(false) // Fetch Categories useEffect(() => { fetch(`${API_BASE}/categories?lang=${i18n.language}`) .then(res => res.json()) .then(setCategories) .catch(console.error) }, [i18n.language]) // Fetch Customer Profile details & Points dynamically const fetchProfile = () => { if (!customer) return fetch(`${API_BASE}/profile/${customer.id}`) .then(res => res.json()) .then(data => { if (data && !data.error) { setDbCustomer(data) setEmailInput(data.email || '') setPhoneInput(data.phone || '') } }) .catch(console.error) } // Fetch Orders const fetchOrders = () => { if (!customer) return setLoadingOrders(true) fetch(`${API_BASE}/orders/customer/${customer.id}`) .then(res => res.json()) .then(data => { if (Array.isArray(data)) { setOrders(data) } }) .catch(console.error) .finally(() => setLoadingOrders(false)) } // Fetch Addresses const fetchAddresses = () => { if (!customer) return setLoadingAddresses(true) fetch(`${API_BASE}/profile/${customer.id}/addresses`) .then(res => res.json()) .then(data => { if (Array.isArray(data)) { setAddresses(data) } }) .catch(console.error) .finally(() => setLoadingAddresses(false)) } useEffect(() => { if (customer) { fetchProfile() fetchOrders() fetchAddresses() } }, [customer]) // Reset Address Form const resetAddressForm = () => { setRecipientName('') setPhone('') setAddressLine('') setSubdistrict('') setDistrict('') setProvince('') setZipcode('') setIsDefault(false) setEditingAddress(null) setShowAddressForm(false) } // Handle Edit Address Click const startEditAddress = (addr: CustomerAddress) => { setEditingAddress(addr) setRecipientName(addr.recipientName) setPhone(addr.phone) setAddressLine(addr.addressLine) setSubdistrict(addr.subdistrict) setDistrict(addr.district) setProvince(addr.province) setZipcode(addr.zipcode) setIsDefault(addr.isDefault) setShowAddressForm(true) } // Handle Add/Edit Address Submission const handleAddressSubmit = async (e: React.FormEvent) => { e.preventDefault() if (!customer) return setSubmittingAddress(true) const payload = { recipientName, phone, addressLine, subdistrict, district, province, zipcode, isDefault } try { const url = editingAddress ? `${API_BASE}/profile/${customer.id}/addresses/${editingAddress.id}` : `${API_BASE}/profile/${customer.id}/addresses` const method = editingAddress ? 'PUT' : 'POST' const res = await fetch(url, { method, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }) if (res.ok) { resetAddressForm() fetchAddresses() } else { const err = await res.json() alert(err.error || 'Failed to save address') } } catch (err) { console.error(err) alert('Failed to connect to server') } finally { setSubmittingAddress(false) } } // Handle Delete Address const handleDeleteAddress = async (addrId: number) => { if (!customer) return if (!confirm('ยืนยันที่จะลบที่อยู่จัดส่งนี้?')) return try { const res = await fetch(`${API_BASE}/profile/${customer.id}/addresses/${addrId}`, { method: 'DELETE' }) if (res.ok) { fetchAddresses() } else { alert('Failed to delete address') } } catch (err) { console.error(err) } } // Handle Set Default Address const handleSetDefault = async (addrId: number) => { if (!customer) return try { const res = await fetch(`${API_BASE}/profile/${customer.id}/addresses/${addrId}/default`, { method: 'PATCH' }) if (res.ok) { fetchAddresses() } } catch (err) { console.error(err) } } // Handle Settings Submit (Update email & phone) const handleSettingsSubmit = async (e: React.FormEvent) => { e.preventDefault() if (!customer) return setSubmittingSettings(true) setSettingsSuccess(false) try { const res = await fetch(`${API_BASE}/profile/${customer.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: emailInput || null, phone: phoneInput || null }) }) if (res.ok) { const updatedCustomer = await res.json() setDbCustomer(updatedCustomer) // Update store if (token) { setAuth(token, updatedCustomer) } setSettingsSuccess(true) setTimeout(() => setSettingsSuccess(false), 3000) } else { const err = await res.json() alert(err.error || 'Failed to update profile') } } catch (err) { console.error(err) alert('Failed to connect to server') } finally { setSubmittingSettings(false) } } const getOrderStatusColor = (status: string) => { switch (status.toUpperCase()) { case 'PAID': return 'bg-emerald-500/10 text-emerald-600 border-emerald-500/20' case 'PENDING_PAYMENT': return 'bg-amber-500/10 text-amber-600 border-amber-500/20' case 'SHIPPED': return 'bg-blue-500/10 text-blue-600 border-blue-500/20' case 'CANCELLED': return 'bg-rose-500/10 text-rose-600 border-rose-500/20' default: return 'bg-spa-stone/10 text-spa-stone border-spa-stone/20' } } const translateStatus = (status: string) => { switch (status.toUpperCase()) { case 'PAID': return 'ชำระเงินสำเร็จ' case 'PENDING_PAYMENT': return 'รอการชำระเงิน' case 'SHIPPED': return 'จัดส่งแล้ว' case 'CANCELLED': return 'ยกเลิกแล้ว' default: return status } } return (
{!customer ? ( /* Login CTA screen */

เข้าสู่ระบบสมาชิก

ล็อกอินเพื่อตรวจสอบประวัติคำสั่งซื้อ สะสมคะแนนสมาชิก และบันทึกสมุดที่อยู่จัดส่งสินค้า

กลับไปเลือกซื้อสินค้า
) : ( /* Logged In Dashboard Layout */
{/* Header Profile Banner */}
{/* User Avatar & Info */}
LINE Profile

{customer.displayName}

{dbCustomer?.phone && ( {dbCustomer.phone} )} {dbCustomer?.email && ( {dbCustomer.email} )}
{/* Point Card Compact */}

คะแนนสะสมของคุณ

{dbCustomer?.points ?? customer.points ?? 0} คะแนน

{/* Dashboard Horizontal Tabs & Content */}
{/* Horizontal Tab UI */}
{/* Tab Display Area */}
{/* 1. ORDERS TAB */} {activeTab === 'orders' && (

ประวัติคำสั่งซื้อทั้งหมด

{loadingOrders ? (
) : orders.length === 0 ? (

ไม่มีประวัติการสั่งซื้อ

คุณยังไม่ได้ทำการสั่งซื้อสินค้าใดๆ กับแบรนด์ของเรา

ไปหน้าช้อปปิ้ง
) : (
{orders.map(order => (
{/* Card Header */}

เลขออเดอร์ #{order.id.toString().padStart(4, '0')}

สั่งเมื่อ {new Date(order.createdAt).toLocaleDateString('th-TH', { year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit' })}

{translateStatus(order.status)}
{/* Card Items */}
{order.items.map(item => (
Product

{item.productName}

{item.variantSize} x {item.quantity}

{formatPrice(item.priceAtPurchase * item.quantity)}

))}
{/* Card Footer */}
{order.trackingNo && (

เลขแทรกพัสดุ: {order.trackingNo}

)}
ยอดรวมสุทธิ: {formatPrice(order.totalAmount)}
))}
)}
)} {/* 2. ADDRESSES TAB */} {activeTab === 'addresses' && (

สมุดที่อยู่จัดส่งของฉัน

{!showAddressForm && ( )}
{/* Address Creation/Editing Form */} {showAddressForm && (

{editingAddress ? 'แก้ไขที่อยู่จัดส่ง' : 'เพิ่มที่อยู่จัดส่งใหม่'}

setRecipientName(e.target.value)} className="w-full bg-spa-light border border-spa-stone/20 rounded-lg p-2.5 text-xs text-pop-black focus:border-spa-forest outline-none transition-all" placeholder="เช่น สมชาย ใจดี" />
setPhone(e.target.value)} className="w-full bg-spa-light border border-spa-stone/20 rounded-lg p-2.5 text-xs text-pop-black focus:border-spa-forest outline-none transition-all" placeholder="เช่น 0812345678" />
setAddressLine(e.target.value)} className="w-full bg-spa-light border border-spa-stone/20 rounded-lg p-2.5 text-xs text-pop-black focus:border-spa-forest outline-none transition-all" placeholder="เช่น 99/9 หมู่ 9 ซอยสุขุมวิท 23" />
{ setSubdistrict(val.subdistrict); setDistrict(val.district); setProvince(val.province); setZipcode(val.zipcode); }} />
setIsDefault(e.target.checked)} className="w-4 h-4 text-spa-forest focus:ring-spa-forest border-spa-stone/30 rounded cursor-pointer" />
)} {loadingAddresses ? (
) : addresses.length === 0 ? (

ไม่มีข้อมูลที่อยู่จัดส่ง

กรุณากดปุ่มเพิ่มที่อยู่ด้านบนเพื่อบันทึกสมุดที่อยู่จัดส่งสินค้าของคุณ

) : (
{addresses.map(addr => (

{addr.recipientName}

{addr.isDefault && ( เริ่มต้น )}

{addr.phone}

{addr.addressLine} ต.{addr.subdistrict} อ.{addr.district} จ.{addr.province} {addr.zipcode}

{!addr.isDefault && ( )}
))}
)}
)} {/* 3. SETTINGS TAB */} {activeTab === 'settings' && (

ข้อมูลติดต่อสมาชิก

{settingsSuccess && (
บันทึกข้อมูลติดต่อของคุณสำเร็จแล้ว
)}
setEmailInput(e.target.value)} className="w-full bg-spa-light border border-spa-stone/20 rounded-lg p-3 text-xs text-pop-black focus:border-spa-forest outline-none transition-all placeholder:text-spa-stone/30" placeholder="เช่น example@email.com" />
setPhoneInput(e.target.value)} className="w-full bg-spa-light border border-spa-stone/20 rounded-lg p-3 text-xs text-pop-black focus:border-spa-forest outline-none transition-all placeholder:text-spa-stone/30" placeholder="เช่น 0812345678" />
)}
)}
) }