Initial commit for homaroma
This commit is contained in:
commit
f2179cfe57
269 files changed
+22635
No files matched your search
@@ -0,0 +1,183 @@
|
||||
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-white/5 bg-night-800/20">
|
||||
<p className="text-cyan-glow 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@irelax.co.th', href: 'mailto:hello@irelax.co.th' },
|
||||
{ icon: '📱', label: 'LINE Official', value: '@irelaxessential', href: '#' },
|
||||
{ icon: '📸', label: 'Instagram', value: '@irelax.essential', 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="glass w-10 h-10 rounded-xl flex items-center justify-center text-lg shrink-0 group-hover:bg-cyan-glow/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-cyan-glow transition-colors">{item.value}</p>
|
||||
</div>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="glass rounded-2xl p-6 border border-white/5 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-cyan-glow font-medium">~2 hours</span>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<span className="text-slate-400">LINE</span>
|
||||
<span className="text-cyan-glow font-medium">~30 minutes</span>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<span className="text-slate-400">Instagram DM</span>
|
||||
<span className="text-cyan-glow 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 glass border border-white/10 hover:border-cyan-glow/30 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 glass border border-white/10 focus:border-cyan-glow/40 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 glass border border-white/10 focus:border-cyan-glow/40 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 glass border border-white/10 focus:border-cyan-glow/40 rounded-xl px-4 py-3.5 bg-night-900 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 glass border border-white/10 focus:border-cyan-glow/40 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-night-900 font-bold uppercase tracking-widest text-sm rounded-xl hover:bg-cyan-glow 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>
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user