Files
homaroma/apps/spa/src/pages/ContactPage.tsx
T

184 lines
9.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useState, useEffect } from 'react'
import Navbar from '../components/Navbar'
import Footer from '../components/Footer'
import { API_BASE, type Category } from '../types'
type FormState = { name: string; email: string; subject: string; message: string }
type Status = 'idle' | 'sending' | 'sent' | 'error'
const SUBJECTS = ['Product Inquiry', 'Order Support', 'Custom Blending', 'Wholesale', 'Partnership', 'Other']
export default function ContactPage() {
const [categories, setCategories] = useState<Category[]>([])
const [form, setForm] = useState<FormState>({ name: '', email: '', subject: '', message: '' })
const [status, setStatus] = useState<Status>('idle')
useEffect(() => {
fetch(`${API_BASE}/categories`).then(r => r.json()).then(setCategories).catch(console.error)
}, [])
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
setForm(prev => ({ ...prev, [e.target.name]: e.target.value }))
}
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
setStatus('sending')
// Simulate API call (replace with real endpoint later)
await new Promise(r => setTimeout(r, 1500))
setStatus('sent')
setForm({ name: '', email: '', subject: '', message: '' })
}
return (
<div className="min-h-screen">
<Navbar categories={categories} />
{/* Header */}
<div className="pt-32 pb-16 px-6 text-center space-y-4 border-b border-spa-stone/10 bg-white border-b border-spa-stone/10">
<p className="text-spa-forest uppercase tracking-[0.4em] text-xs font-semibold opacity-70">Get in Touch</p>
<h1 className="text-5xl font-bold">Contact Us</h1>
<p className="text-slate-400 max-w-lg mx-auto">
Have a question, custom request, or partnership idea? We'd love to hear from you.
</p>
</div>
<div className="max-w-6xl mx-auto px-6 py-16 grid md:grid-cols-5 gap-16">
{/* Contact Info */}
<div className="md:col-span-2 space-y-8">
<div>
<h2 className="font-bold text-xl mb-6">Reach Us Directly</h2>
<div className="space-y-5">
{[
{ icon: '📧', label: 'Email', value: 'hello@homaroma.shop', href: 'mailto:hello@homaroma.shop' },
{ icon: '📱', label: 'LINE Official', value: '@homaroma', href: '#' },
{ icon: '📸', label: 'Instagram', value: '@homaroma', href: '#' },
{ icon: '📍', label: 'Studio', value: 'Bangkok, Thailand', href: '#' },
].map(item => (
<a key={item.label} href={item.href} className="flex items-start gap-4 group">
<div className="bg-white shadow-sm border border-spa-stone/10 w-10 h-10 rounded-xl flex items-center justify-center text-lg shrink-0 group-hover:bg-spa-forest/10 transition-colors">
{item.icon}
</div>
<div>
<p className="text-xs text-slate-500 uppercase tracking-widest">{item.label}</p>
<p className="text-white text-sm font-medium group-hover:text-spa-forest transition-colors">{item.value}</p>
</div>
</a>
))}
</div>
</div>
<div className="bg-white shadow-sm border border-spa-stone/10 rounded-2xl p-6 border border-spa-stone/10 space-y-3">
<h3 className="font-bold text-sm uppercase tracking-widest">Response Time</h3>
<div className="space-y-2 text-sm">
<div className="flex justify-between">
<span className="text-slate-400">Email</span>
<span className="text-spa-forest font-medium">~2 hours</span>
</div>
<div className="flex justify-between">
<span className="text-slate-400">LINE</span>
<span className="text-spa-forest font-medium">~30 minutes</span>
</div>
<div className="flex justify-between">
<span className="text-slate-400">Instagram DM</span>
<span className="text-spa-forest font-medium">~4 hours</span>
</div>
</div>
<p className="text-[10px] text-slate-600 pt-2 uppercase tracking-wider">Mon–Sat, 9:00–18:00 (ICT)</p>
</div>
</div>
{/* Contact Form */}
<div className="md:col-span-3">
{status === 'sent' ? (
<div className="h-full flex items-center justify-center">
<div className="text-center space-y-5 py-16">
<div className="text-6xl animate-bounce">✉️</div>
<h2 className="text-2xl font-bold">Message Sent!</h2>
<p className="text-slate-400">Thank you for reaching out. We'll get back to you within 2 hours.</p>
<button
onClick={() => setStatus('idle')}
className="mt-4 px-8 py-3 bg-white shadow-sm border border-spa-stone/10 border border-spa-stone/10 hover:border-spa-forest font-bold uppercase tracking-widest text-xs transition-all rounded-lg"
>
Send Another
</button>
</div>
</div>
) : (
<form onSubmit={handleSubmit} className="space-y-5">
<div className="grid md:grid-cols-2 gap-5">
<div className="space-y-2">
<label className="text-xs uppercase tracking-widest text-slate-400">Full Name *</label>
<input
required
type="text"
name="name"
value={form.name}
onChange={handleChange}
placeholder="Your name"
className="w-full bg-white shadow-sm border border-spa-stone/10 border border-spa-stone/10 focus:border-spa-forest rounded-xl px-4 py-3.5 bg-transparent outline-none text-sm text-white placeholder-slate-600 transition-colors"
/>
</div>
<div className="space-y-2">
<label className="text-xs uppercase tracking-widest text-slate-400">Email *</label>
<input
required
type="email"
name="email"
value={form.email}
onChange={handleChange}
placeholder="your@email.com"
className="w-full bg-white shadow-sm border border-spa-stone/10 border border-spa-stone/10 focus:border-spa-forest rounded-xl px-4 py-3.5 bg-transparent outline-none text-sm text-white placeholder-slate-600 transition-colors"
/>
</div>
</div>
<div className="space-y-2">
<label className="text-xs uppercase tracking-widest text-slate-400">Subject *</label>
<select
required
name="subject"
value={form.subject}
onChange={handleChange}
className="w-full bg-white shadow-sm border border-spa-stone/10 border border-spa-stone/10 focus:border-spa-forest rounded-xl px-4 py-3.5 bg-white outline-none text-sm text-white transition-colors"
>
<option value="" disabled>Select a subject</option>
{SUBJECTS.map(s => <option key={s} value={s}>{s}</option>)}
</select>
</div>
<div className="space-y-2">
<label className="text-xs uppercase tracking-widest text-slate-400">Message *</label>
<textarea
required
name="message"
value={form.message}
onChange={handleChange}
rows={6}
placeholder="Tell us about your inquiry..."
className="w-full bg-white shadow-sm border border-spa-stone/10 border border-spa-stone/10 focus:border-spa-forest rounded-xl px-4 py-3.5 bg-transparent outline-none text-sm text-white placeholder-slate-600 resize-none transition-colors"
/>
</div>
<button
type="submit"
disabled={status === 'sending'}
className="w-full py-4 bg-white text-spa-forest font-bold uppercase tracking-widest text-sm rounded-xl hover:bg-spa-forest text-white hover:shadow-[0_0_25px_rgba(102,252,241,0.4)] transition-all duration-500 disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-3"
>
{status === 'sending' ? (
<>
<svg className="animate-spin w-4 h-4" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
</svg>
Sending...
</>
) : 'Send Message →'}
</button>
</form>
)}
</div>
</div>
<Footer categories={categories} />
</div>
)
}