// Nueva versión ampliada del proyecto inspirada en planning.wedding
// Incluye más módulos: crear sitio completo, cronograma, presupuesto, checklist, galería,
// secciones personalizadas, RSVPs avanzados, mesas, alojamiento, transporte, módulo de regalos, etc.
// --- NOTA ---
// Este es un front-end unificado en un solo archivo para demostración. En producción debe dividirse por componentes.
import React, { useState, useEffect, useRef } from "react";
import { MapContainer, TileLayer, Marker, Popup, useMapEvents } from "react-leaflet";
import L from "leaflet";
import html2canvas from "html2canvas";
import "leaflet/dist/leaflet.css";
delete L.Icon.Default.prototype._getIconUrl;
L.Icon.Default.mergeOptions({
iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'),
iconUrl: require('leaflet/dist/images/marker-icon.png'),
shadowUrl: require('leaflet/dist/images/marker-shadow.png'),
});
// =============================
// Utilidad LocalStorage
// =============================
function useLocalStorage(key, initialValue) {
const [state, setState] = useState(() => {
try {
const v = localStorage.getItem(key);
return v ? JSON.parse(v) : initialValue;
} catch (e) { return initialValue; }
});
useEffect(() => {
try { localStorage.setItem(key, JSON.stringify(state)); } catch {}
}, [key, state]);
return [state, setState];
}
// =============================
// Constructor de Mapa
// =============================
function MapBuilder({ markers, setMarkers, center=[14.6349,-90.5068], zoom=13 }) {
function AddMarkerOnClick() {
useMapEvents({ click(e) {
const { lat, lng } = e.latlng;
const label = prompt("Nombre del punto");
if(label) setMarkers(m => [...m, { id: Date.now(), label, lat, lng }]);
}});
return null;
}
return (
{markers.map(m => (
{m.label}
))}
);
}
// =============================
// Componente principal
// =============================
export default function EventPage() {
// ---------------- Datos principales del evento ----------------
const [event, setEvent] = useLocalStorage("event_data", {
title: "Nuestra Boda",
subtitle: "Bienvenidos a nuestro sitio oficial",
date: "2026-06-12",
time: "16:00",
locationName: "Hacienda La Esperanza",
description: "Acompáñanos a celebrar este día tan especial.",
heroImage: null,
themeColor: "pink-600",
});
// ---------------- Módulos adicionales ----------------
const [markers, setMarkers] = useLocalStorage("event_markers", []);
const [guests, setGuests] = useLocalStorage("event_guests", []);
const [checklist, setChecklist] = useLocalStorage("event_checklist", []);
const [timeline, setTimeline] = useLocalStorage("event_timeline", []);
const [budget, setBudget] = useLocalStorage("event_budget", []);
const [gallery, setGallery] = useLocalStorage("event_gallery", []);
const [lodging, setLodging] = useLocalStorage("event_lodging", []);
const [transport, setTransport] = useLocalStorage("event_transport", []);
const [gifts, setGifts] = useLocalStorage("event_gifts", []);
const [adminMode, setAdminMode] = useState(false);
const inviteRef = useRef(null);
// =============================
// Funciones
// =============================
// Invitación PNG
function downloadInvitation() {
if(!inviteRef.current) return;
html2canvas(inviteRef.current, { scale: 2 }).then(canvas => {
const a = document.createElement("a");
a.download = "invitacion.png";
a.href = canvas.toDataURL();
a.click();
});
}
// Añadir elementos genéricos
function addItemTo(setter, list, item) {
setter([...list, { id: Date.now(), ...item }]);
}
function removeItemFrom(setter, list, id) {
setter(list.filter(x => x.id !== id));
}
// =============================
// UI
// =============================
return (
{/* Header */}
{event.title}
{/* Hero */}
{/* Mapa */}
{/* Invitación */}
Invitación virtual
{event.title}
{event.date} — {event.time}
{event.locationName}
{/* Módulo: Invitados */}
Invitados
{guests.map(g => (
))}
{adminMode && (
)}
{/* Checklist */}
Checklist
{checklist.map(c => (
-
{c.text}
))}
{adminMode && (
)}
{/* Cronograma */}
Cronograma del Evento
{timeline.map(t => (
{t.time} — {t.activity}
))}
{adminMode && (
)}
{/* Presupuesto */}
Presupuesto
{budget.map(b => (
{b.label}: Q{b.amount}
))}
{adminMode && (
)}
);
}
top of page
Mentiras
Presentación en Parque las Americas
Fly me to the moon
Presentación en Duplo Café
Killing me Softly
Presentación en Parque las Americas
Every Breath you Take
Presentación en Shiraz
Feat. Silber García - Percusión
Inolvidable
Presentación Parque la Americas
bottom of page