feat: compact homepage with CTA buttons, new contact page, remove large text section
This commit is contained in:
@@ -0,0 +1,194 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { useLanguage } from '@/lib/i18n';
|
||||||
|
|
||||||
|
const gold = '#E8A849';
|
||||||
|
const navy = '#010D1E';
|
||||||
|
const cream = '#f5f0e8';
|
||||||
|
|
||||||
|
const copy = {
|
||||||
|
en: {
|
||||||
|
title: 'Contact Us',
|
||||||
|
subtitle: 'Get in touch with us',
|
||||||
|
phone: 'Phone',
|
||||||
|
email: 'Email',
|
||||||
|
whatsapp: 'WhatsApp',
|
||||||
|
location: 'Location',
|
||||||
|
address: 'Otavalo, Imbabura, Ecuador',
|
||||||
|
send_message: 'Send us a message',
|
||||||
|
form_name: 'Your Name',
|
||||||
|
form_email: 'Your Email',
|
||||||
|
form_message: 'Message',
|
||||||
|
form_submit: 'Send Message',
|
||||||
|
form_sending: 'Sending...',
|
||||||
|
form_success: 'Message sent successfully!',
|
||||||
|
form_error: 'Failed to send message. Please try again.',
|
||||||
|
},
|
||||||
|
es: {
|
||||||
|
title: 'Contáctenos',
|
||||||
|
subtitle: 'Póngase en contacto con nosotros',
|
||||||
|
phone: 'Teléfono',
|
||||||
|
email: 'Correo',
|
||||||
|
whatsapp: 'WhatsApp',
|
||||||
|
location: 'Ubicación',
|
||||||
|
address: 'Otavalo, Imbabura, Ecuador',
|
||||||
|
send_message: 'Envíenos un mensaje',
|
||||||
|
form_name: 'Su Nombre',
|
||||||
|
form_email: 'Su Correo',
|
||||||
|
form_message: 'Mensaje',
|
||||||
|
form_submit: 'Enviar Mensaje',
|
||||||
|
form_sending: 'Enviando...',
|
||||||
|
form_success: '¡Mensaje enviado exitosamente!',
|
||||||
|
form_error: 'Error al enviar el mensaje. Intente de nuevo.',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function ContactPage() {
|
||||||
|
const language = useLanguage();
|
||||||
|
const t = copy[language];
|
||||||
|
const [form, setForm] = useState({ name: '', email: '', message: '' });
|
||||||
|
const [status, setStatus] = useState<'idle' | 'sending' | 'success' | 'error'>('idle');
|
||||||
|
|
||||||
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setStatus('sending');
|
||||||
|
try {
|
||||||
|
const res = await fetch('/api/contact', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(form),
|
||||||
|
});
|
||||||
|
if (res.ok) {
|
||||||
|
setStatus('success');
|
||||||
|
setForm({ name: '', email: '', message: '' });
|
||||||
|
} else {
|
||||||
|
setStatus('error');
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
setStatus('error');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main style={{ minHeight: 'calc(100vh - 56px)', background: navy, color: cream, padding: '3rem 2rem' }}>
|
||||||
|
<div style={{ maxWidth: '900px', margin: '0 auto' }}>
|
||||||
|
<h1 style={{ fontSize: 'clamp(32px, 5vw, 48px)', fontWeight: 400, fontStyle: 'italic', marginBottom: '0.5rem', color: cream }}>
|
||||||
|
{t.title}
|
||||||
|
</h1>
|
||||||
|
<p style={{ fontSize: '16px', color: 'rgba(245,240,232,0.7)', marginBottom: '3rem' }}>
|
||||||
|
{t.subtitle}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))', gap: '2rem', marginBottom: '3rem' }}>
|
||||||
|
{/* Phone */}
|
||||||
|
<div style={{ background: 'rgba(245,240,232,0.06)', borderRadius: '12px', padding: '1.5rem', border: '1px solid rgba(245,240,232,0.12)' }}>
|
||||||
|
<div style={{ fontSize: '24px', marginBottom: '0.5rem' }}>📞</div>
|
||||||
|
<div style={{ fontSize: '12px', textTransform: 'uppercase', letterSpacing: '0.1em', color: gold, marginBottom: '0.25rem' }}>{t.phone}</div>
|
||||||
|
<div style={{ fontSize: '16px' }}>+593 99 XXX XXXX</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Email */}
|
||||||
|
<div style={{ background: 'rgba(245,240,232,0.06)', borderRadius: '12px', padding: '1.5rem', border: '1px solid rgba(245,240,232,0.12)' }}>
|
||||||
|
<div style={{ fontSize: '24px', marginBottom: '0.5rem' }}>✉️</div>
|
||||||
|
<div style={{ fontSize: '12px', textTransform: 'uppercase', letterSpacing: '0.1em', color: gold, marginBottom: '0.25rem' }}>{t.email}</div>
|
||||||
|
<div style={{ fontSize: '16px' }}>info@lahuasca.com</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* WhatsApp */}
|
||||||
|
<div style={{ background: 'rgba(245,240,232,0.06)', borderRadius: '12px', padding: '1.5rem', border: '1px solid rgba(245,240,232,0.12)' }}>
|
||||||
|
<div style={{ fontSize: '24px', marginBottom: '0.5rem' }}>💬</div>
|
||||||
|
<div style={{ fontSize: '12px', textTransform: 'uppercase', letterSpacing: '0.1em', color: gold, marginBottom: '0.25rem' }}>{t.whatsapp}</div>
|
||||||
|
<div style={{ fontSize: '16px' }}>+593 99 XXX XXXX</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Location */}
|
||||||
|
<div style={{ background: 'rgba(245,240,232,0.06)', borderRadius: '12px', padding: '1.5rem', border: '1px solid rgba(245,240,232,0.12)' }}>
|
||||||
|
<div style={{ fontSize: '24px', marginBottom: '0.5rem' }}>📍</div>
|
||||||
|
<div style={{ fontSize: '12px', textTransform: 'uppercase', letterSpacing: '0.1em', color: gold, marginBottom: '0.25rem' }}>{t.location}</div>
|
||||||
|
<div style={{ fontSize: '16px' }}>{t.address}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Contact Form */}
|
||||||
|
<div style={{ background: 'rgba(245,240,232,0.04)', borderRadius: '16px', padding: '2rem', border: '1px solid rgba(245,240,232,0.1)' }}>
|
||||||
|
<h2 style={{ fontSize: '20px', fontWeight: 600, marginBottom: '1.5rem', color: cream }}>
|
||||||
|
{t.send_message}
|
||||||
|
</h2>
|
||||||
|
<form onSubmit={handleSubmit} style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder={t.form_name}
|
||||||
|
value={form.name}
|
||||||
|
onChange={(e) => setForm({ ...form, name: e.target.value })}
|
||||||
|
required
|
||||||
|
style={{
|
||||||
|
padding: '0.875rem 1rem',
|
||||||
|
background: 'rgba(245,240,232,0.08)',
|
||||||
|
border: '1px solid rgba(245,240,232,0.2)',
|
||||||
|
borderRadius: '8px',
|
||||||
|
color: cream,
|
||||||
|
fontSize: '15px',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
placeholder={t.form_email}
|
||||||
|
value={form.email}
|
||||||
|
onChange={(e) => setForm({ ...form, email: e.target.value })}
|
||||||
|
required
|
||||||
|
style={{
|
||||||
|
padding: '0.875rem 1rem',
|
||||||
|
background: 'rgba(245,240,232,0.08)',
|
||||||
|
border: '1px solid rgba(245,240,232,0.2)',
|
||||||
|
borderRadius: '8px',
|
||||||
|
color: cream,
|
||||||
|
fontSize: '15px',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<textarea
|
||||||
|
placeholder={t.form_message}
|
||||||
|
value={form.message}
|
||||||
|
onChange={(e) => setForm({ ...form, message: e.target.value })}
|
||||||
|
required
|
||||||
|
rows={5}
|
||||||
|
style={{
|
||||||
|
padding: '0.875rem 1rem',
|
||||||
|
background: 'rgba(245,240,232,0.08)',
|
||||||
|
border: '1px solid rgba(245,240,232,0.2)',
|
||||||
|
borderRadius: '8px',
|
||||||
|
color: cream,
|
||||||
|
fontSize: '15px',
|
||||||
|
resize: 'vertical',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={status === 'sending'}
|
||||||
|
style={{
|
||||||
|
padding: '0.875rem 1.5rem',
|
||||||
|
background: gold,
|
||||||
|
color: navy,
|
||||||
|
border: 'none',
|
||||||
|
borderRadius: '8px',
|
||||||
|
fontSize: '15px',
|
||||||
|
fontWeight: 600,
|
||||||
|
cursor: status === 'sending' ? 'wait' : 'pointer',
|
||||||
|
opacity: status === 'sending' ? 0.7 : 1,
|
||||||
|
transition: 'opacity 200ms',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{status === 'sending' ? t.form_sending : t.form_submit}
|
||||||
|
</button>
|
||||||
|
{status === 'success' && (
|
||||||
|
<p style={{ color: '#4CAF50', margin: 0 }}>{t.form_success}</p>
|
||||||
|
)}
|
||||||
|
{status === 'error' && (
|
||||||
|
<p style={{ color: '#f44336', margin: 0 }}>{t.form_error}</p>
|
||||||
|
)}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
+97
-50
@@ -5,6 +5,7 @@ import Slideshow from '@/components/Slideshow';
|
|||||||
import CalendarStrip from '@/components/CalendarStrip';
|
import CalendarStrip from '@/components/CalendarStrip';
|
||||||
import WeatherWidget from '@/components/WeatherWidget';
|
import WeatherWidget from '@/components/WeatherWidget';
|
||||||
import LanguageSwitcher from '@/components/LanguageSwitcher';
|
import LanguageSwitcher from '@/components/LanguageSwitcher';
|
||||||
|
import Link from 'next/link';
|
||||||
import { t, useLanguage } from '@/lib/i18n';
|
import { t, useLanguage } from '@/lib/i18n';
|
||||||
|
|
||||||
const gold = '#E8A849';
|
const gold = '#E8A849';
|
||||||
@@ -13,39 +14,21 @@ const cream = '#f5f0e8';
|
|||||||
|
|
||||||
const homeCopy = {
|
const homeCopy = {
|
||||||
en: {
|
en: {
|
||||||
title: 'La Huasca',
|
tagline: 'Welcome to the Heart of Imbabura',
|
||||||
subtitle: 'A mountain retreat with warm hospitality and local flavor.',
|
cta_rooms: 'Book a Room',
|
||||||
highlights: ['common.hotel', 'common.restaurant', 'common.andean_highlands'],
|
cta_menu: 'View Our Menu',
|
||||||
|
cta_contact: 'Contact Us',
|
||||||
},
|
},
|
||||||
es: {
|
es: {
|
||||||
title: 'La Huasca',
|
tagline: 'Bienvenidos al Corazón de Imbabura',
|
||||||
subtitle: 'Un refugio de montaña con hospitalidad cálida y sabor local.',
|
cta_rooms: 'Reservar Habitación',
|
||||||
highlights: ['common.hotel', 'common.restaurant', 'common.andean_highlands'],
|
cta_menu: 'Ver Menú',
|
||||||
|
cta_contact: 'Contáctenos',
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
const fallbackTaglineKey = 'common.home_tagline';
|
|
||||||
|
|
||||||
export default function HomePage() {
|
export default function HomePage() {
|
||||||
const language = useLanguage();
|
const language = useLanguage();
|
||||||
const [tagline, setTagline] = useState(t(fallbackTaglineKey, language));
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
let cancelled = false;
|
|
||||||
const fallbackTagline = t(fallbackTaglineKey, language);
|
|
||||||
setTagline(fallbackTagline);
|
|
||||||
fetch('/api/site-assets?key=tagline')
|
|
||||||
.then((r) => r.json())
|
|
||||||
.then((j) => {
|
|
||||||
if (!cancelled && j.data) setTagline(j.data);
|
|
||||||
})
|
|
||||||
.catch(() => {});
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
cancelled = true;
|
|
||||||
};
|
|
||||||
}, [language]);
|
|
||||||
|
|
||||||
const copy = homeCopy[language];
|
const copy = homeCopy[language];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -57,50 +40,114 @@ export default function HomePage() {
|
|||||||
|
|
||||||
<Slideshow />
|
<Slideshow />
|
||||||
|
|
||||||
|
{/* Compact CTA section */}
|
||||||
<section
|
<section
|
||||||
style={{
|
style={{
|
||||||
padding: 'clamp(3rem, 9vw, 7rem) 2rem',
|
padding: 'clamp(1.5rem, 4vw, 2.5rem) 2rem',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
|
gap: '1.5rem',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<p
|
<p
|
||||||
style={{
|
style={{
|
||||||
fontFamily: 'monospace',
|
fontFamily: 'monospace',
|
||||||
fontSize: '12px',
|
fontSize: '11px',
|
||||||
letterSpacing: '0.18em',
|
letterSpacing: '0.18em',
|
||||||
textTransform: 'uppercase',
|
textTransform: 'uppercase',
|
||||||
color: gold,
|
color: gold,
|
||||||
margin: '0 0 1rem',
|
margin: 0,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{tagline}
|
{copy.tagline}
|
||||||
</p>
|
</p>
|
||||||
<h1
|
|
||||||
|
{/* CTA Buttons */}
|
||||||
|
<div style={{ display: 'flex', gap: '1rem', flexWrap: 'wrap', justifyContent: 'center' }}>
|
||||||
|
<Link
|
||||||
|
href="/rooms"
|
||||||
style={{
|
style={{
|
||||||
fontSize: 'clamp(44px, 7vw, 84px)',
|
display: 'inline-flex',
|
||||||
fontWeight: 400,
|
alignItems: 'center',
|
||||||
fontStyle: 'italic',
|
gap: '0.5rem',
|
||||||
lineHeight: 1.08,
|
padding: '0.875rem 1.75rem',
|
||||||
margin: '0 0 1.25rem',
|
background: gold,
|
||||||
color: cream,
|
color: navy,
|
||||||
|
fontWeight: 600,
|
||||||
|
fontSize: '15px',
|
||||||
|
borderRadius: '8px',
|
||||||
|
textDecoration: 'none',
|
||||||
|
transition: 'transform 200ms, box-shadow 200ms',
|
||||||
|
boxShadow: '0 4px 12px rgba(232,168,73,0.25)',
|
||||||
|
}}
|
||||||
|
onMouseEnter={(e) => {
|
||||||
|
e.currentTarget.style.transform = 'translateY(-2px)';
|
||||||
|
e.currentTarget.style.boxShadow = '0 6px 20px rgba(232,168,73,0.35)';
|
||||||
|
}}
|
||||||
|
onMouseLeave={(e) => {
|
||||||
|
e.currentTarget.style.transform = 'translateY(0)';
|
||||||
|
e.currentTarget.style.boxShadow = '0 4px 12px rgba(232,168,73,0.25)';
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{copy.title}
|
🛏️ {copy.cta_rooms}
|
||||||
</h1>
|
</Link>
|
||||||
<p style={{ fontSize: '18px', lineHeight: 1.55, color: 'rgba(245,240,232,0.78)', maxWidth: '52ch', margin: '0 0 2rem' }}>
|
<Link
|
||||||
{copy.highlights.map((key, index) => (
|
href="/menu"
|
||||||
<span key={key}>
|
style={{
|
||||||
{t(key, language)}
|
display: 'inline-flex',
|
||||||
{index < copy.highlights.length - 1 ? ' · ' : ''}
|
alignItems: 'center',
|
||||||
</span>
|
gap: '0.5rem',
|
||||||
))}
|
padding: '0.875rem 1.75rem',
|
||||||
</p>
|
background: 'transparent',
|
||||||
<p style={{ fontSize: '16px', lineHeight: 1.65, color: 'rgba(245,240,232,0.7)', maxWidth: '58ch', margin: 0 }}>
|
color: cream,
|
||||||
{copy.subtitle}
|
fontWeight: 600,
|
||||||
</p>
|
fontSize: '15px',
|
||||||
|
borderRadius: '8px',
|
||||||
|
textDecoration: 'none',
|
||||||
|
border: `2px solid ${gold}`,
|
||||||
|
transition: 'background 200ms, color 200ms',
|
||||||
|
}}
|
||||||
|
onMouseEnter={(e) => {
|
||||||
|
e.currentTarget.style.background = gold;
|
||||||
|
e.currentTarget.style.color = navy;
|
||||||
|
}}
|
||||||
|
onMouseLeave={(e) => {
|
||||||
|
e.currentTarget.style.background = 'transparent';
|
||||||
|
e.currentTarget.style.color = cream;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
🍽️ {copy.cta_menu}
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
href="/contact"
|
||||||
|
style={{
|
||||||
|
display: 'inline-flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: '0.5rem',
|
||||||
|
padding: '0.875rem 1.75rem',
|
||||||
|
background: 'transparent',
|
||||||
|
color: 'rgba(245,240,232,0.8)',
|
||||||
|
fontWeight: 600,
|
||||||
|
fontSize: '15px',
|
||||||
|
borderRadius: '8px',
|
||||||
|
textDecoration: 'none',
|
||||||
|
border: '2px solid rgba(245,240,232,0.3)',
|
||||||
|
transition: 'border-color 200ms, color 200ms',
|
||||||
|
}}
|
||||||
|
onMouseEnter={(e) => {
|
||||||
|
e.currentTarget.style.borderColor = 'rgba(245,240,232,0.6)';
|
||||||
|
e.currentTarget.style.color = cream;
|
||||||
|
}}
|
||||||
|
onMouseLeave={(e) => {
|
||||||
|
e.currentTarget.style.borderColor = 'rgba(245,240,232,0.3)';
|
||||||
|
e.currentTarget.style.color = 'rgba(245,240,232,0.8)';
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
✉️ {copy.cta_contact}
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<CalendarStrip />
|
<CalendarStrip />
|
||||||
|
|||||||
Reference in New Issue
Block a user