Add full SEO optimization for Spanglish social and language events
- Add comprehensive metadata to root layout with Open Graph, Twitter cards - Create dynamic sitemap.ts for all pages and events - Create robots.ts with proper allow/disallow rules - Add JSON-LD Event structured data to event detail pages - Add page-specific metadata to events, community, contact, FAQ pages - Add FAQ structured data schema - Update footer with local SEO text for Asunción, Paraguay - Add web manifest for mobile SEO - Create 404 page with proper noindex - Optimize image alt text and add lazy loading - Add NEXT_PUBLIC_SITE_URL env variable - Add about/ folder to gitignore
This commit is contained in:
@@ -225,16 +225,18 @@ export default function BookingPage() {
|
||||
newErrors.firstName = t('booking.form.errors.firstNameRequired');
|
||||
}
|
||||
|
||||
if (!formData.lastName.trim() || formData.lastName.length < 2) {
|
||||
newErrors.lastName = t('booking.form.errors.lastNameRequired');
|
||||
// lastName is optional - only validate if provided
|
||||
if (formData.lastName.trim() && formData.lastName.length < 2) {
|
||||
newErrors.lastName = t('booking.form.errors.lastNameTooShort');
|
||||
}
|
||||
|
||||
if (!formData.email.trim() || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
|
||||
newErrors.email = t('booking.form.errors.emailInvalid');
|
||||
}
|
||||
|
||||
if (!formData.phone.trim() || formData.phone.length < 6) {
|
||||
newErrors.phone = t('booking.form.errors.phoneRequired');
|
||||
// phone is optional - only validate if provided
|
||||
if (formData.phone.trim() && formData.phone.length < 6) {
|
||||
newErrors.phone = t('booking.form.errors.phoneTooShort');
|
||||
}
|
||||
|
||||
// RUC validation (optional field - only validate if filled)
|
||||
@@ -915,14 +917,22 @@ export default function BookingPage() {
|
||||
error={errors.firstName}
|
||||
required
|
||||
/>
|
||||
<Input
|
||||
label={t('booking.form.lastName')}
|
||||
value={formData.lastName}
|
||||
onChange={(e) => setFormData({ ...formData, lastName: e.target.value })}
|
||||
placeholder={t('booking.form.lastNamePlaceholder')}
|
||||
error={errors.lastName}
|
||||
required
|
||||
/>
|
||||
<div>
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<label className="block text-sm font-medium text-gray-700">
|
||||
{t('booking.form.lastName')}
|
||||
</label>
|
||||
<span className="text-xs text-gray-400">
|
||||
({locale === 'es' ? 'Opcional' : 'Optional'})
|
||||
</span>
|
||||
</div>
|
||||
<Input
|
||||
value={formData.lastName}
|
||||
onChange={(e) => setFormData({ ...formData, lastName: e.target.value })}
|
||||
placeholder={t('booking.form.lastNamePlaceholder')}
|
||||
error={errors.lastName}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@@ -938,14 +948,20 @@ export default function BookingPage() {
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<label className="block text-sm font-medium text-gray-700">
|
||||
{t('booking.form.phone')}
|
||||
</label>
|
||||
<span className="text-xs text-gray-400">
|
||||
({locale === 'es' ? 'Opcional' : 'Optional'})
|
||||
</span>
|
||||
</div>
|
||||
<Input
|
||||
label={t('booking.form.phone')}
|
||||
type="tel"
|
||||
value={formData.phone}
|
||||
onChange={(e) => setFormData({ ...formData, phone: e.target.value })}
|
||||
placeholder={t('booking.form.phonePlaceholder')}
|
||||
error={errors.phone}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user