cambios propuestos por dru
This commit is contained in:
+66
-30
@@ -3,38 +3,39 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>MAY Studio — Peluquería en Barcelona</title>
|
||||
<meta name="description" content="MAY Studio, peluquería en Horta, Barcelona. Cortes, color, peinados y tratamientos para señoras, caballeros y niños.">
|
||||
<title>MAY STUDIO — Peluquería en Barcelona</title>
|
||||
<meta name="description" content="MAY STUDIO, peluquería en Horta, Barcelona. Cortes, color, peinados y tratamientos para señoras, caballeros y niños.">
|
||||
<link rel="icon" href="/favicon.ico" sizes="any">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=DM+Serif+Display&family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="/style.css">
|
||||
<script defer src="https://umami.darma.cc/script.js" data-website-id="2653f3ec-6c3f-422f-b91c-3b6a7f3fe73e"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- NAV -->
|
||||
<nav class="nav">
|
||||
<div class="container nav-inner">
|
||||
<a href="#" class="logo">MAY <span>Studio</span></a>
|
||||
<a href="#" class="logo">MAY <span>STUDIO</span></a>
|
||||
<ul class="nav-links">
|
||||
<li><a href="#profesional">La profesional</a></li>
|
||||
<li><a href="#galeria">Nuestro trabajo</a></li>
|
||||
<li><a href="#reservar">Reservar</a></li>
|
||||
<li><a href="#contacto">Contacto</a></li>
|
||||
</ul>
|
||||
<a href="tel:+34933333333" class="btn btn-primary btn-nav">Llamar</a>
|
||||
<a href="tel:+34690918815" class="btn btn-primary btn-nav">Llamar</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- HERO -->
|
||||
<header class="hero">
|
||||
<div class="hero-bg">
|
||||
<img src="/assets/hero.jpg" alt="Interior del salón MAY Studio">
|
||||
<img src="/assets/hero.jpg" alt="Interior del salón MAY STUDIO">
|
||||
</div>
|
||||
<div class="container hero-content">
|
||||
<h1>MAY Studio<br>Tu peluquería en Horta</h1>
|
||||
<h1>MAY STUDIO<br>Tu peluquería en Horta</h1>
|
||||
<p class="hero-sub">Cortes, color, peinados y tratamientos capilares para toda la familia. Un espacio pensado para ti.</p>
|
||||
<div class="hero-actions">
|
||||
<a href="#reservar" class="btn btn-primary">Reservar cita</a>
|
||||
@@ -48,15 +49,15 @@
|
||||
<div class="container">
|
||||
<div class="profesional-grid">
|
||||
<div class="profesional-img">
|
||||
<img src="/assets/may.jpg" alt="Mayra, peluquera profesional en MAY Studio">
|
||||
<img src="/assets/may.jpg" alt="Mayra, peluquera profesional en MAY STUDIO">
|
||||
</div>
|
||||
<div class="profesional-info">
|
||||
<h3>Mayra</h3>
|
||||
<p class="profesional-role">Peluquera & fundadora</p>
|
||||
<p>Soy Mayra, fundadora de MAY Studio, un espacio dedicado al cuidado del cabello con un enfoque personalizado.</p>
|
||||
<p>Soy Mayra, fundadora de MAY STUDIO, un espacio dedicado al cuidado del cabello con un enfoque personalizado.</p>
|
||||
<p>Estoy especializada en color, mechas y cortes, buscando siempre resultados naturales, equilibrados y elegantes.</p>
|
||||
<p>Cada cliente recibe una atención individualizada, analizando su cabello y su estilo para crear un resultado que sea bonito, favorecedor y fácil de mantener día a día.</p>
|
||||
<p>MAY Studio nace con la idea de ofrecer un ambiente tranquilo donde el cuidado del cabello y la atención al detalle son lo más importante.</p>
|
||||
<p>MAY STUDIO nace con la idea de ofrecer un ambiente tranquilo donde el cuidado del cabello y la atención al detalle son lo más importante.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -66,7 +67,7 @@
|
||||
<section id="galeria" class="section section-alt">
|
||||
<div class="container">
|
||||
<h2 class="section-title">Nuestro trabajo</h2>
|
||||
<p class="section-subtitle">Explora algunos de los estilos y transformaciones que creamos en MAY Studio. Haz clic en cualquier imagen para ampliar.</p>
|
||||
<p class="section-subtitle">Explora algunos de los estilos y transformaciones que creamos en MAY STUDIO. Haz clic en cualquier imagen para ampliar.</p>
|
||||
<div class="gallery-grid">
|
||||
<div class="gallery-item"><img src="/assets/galeria-1.jpg" alt="Trabajo de peluquería"></div>
|
||||
<div class="gallery-item"><img src="/assets/galeria-2.jpg" alt="Trabajo de peluquería"></div>
|
||||
@@ -147,8 +148,8 @@
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label for="email">Email *</label>
|
||||
<input type="email" id="email" name="email" autocomplete="email" required>
|
||||
<label for="email">Email (opcional)</label>
|
||||
<input type="email" id="email" name="email" autocomplete="email">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="telefono">Teléfono *</label>
|
||||
@@ -159,7 +160,7 @@
|
||||
<label for="mensaje">Mensaje (opcional)</label>
|
||||
<textarea id="mensaje" name="mensaje" rows="2" placeholder="Algo que debamos saber…"></textarea>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary" id="booking-submit">Confirmar reserva</button>
|
||||
<button type="submit" class="btn btn-primary" id="booking-submit" disabled>Confirmar reserva</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@@ -175,22 +176,22 @@
|
||||
<div class="contact-info">
|
||||
<div class="contact-item">
|
||||
<strong>Dirección</strong>
|
||||
<p>Carrer d'Horta, 12<br>08032 Barcelona (Horta)</p>
|
||||
<p>Carrer Pintor Josep Pinos, 22<br>08031 Barcelona</p>
|
||||
</div>
|
||||
<div class="contact-item">
|
||||
<strong>Teléfono</strong>
|
||||
<p><a href="tel:+34933333333">933 333 333</a></p>
|
||||
<p><a href="tel:+34690918815">690 918 815</a></p>
|
||||
</div>
|
||||
<div class="contact-item">
|
||||
<strong>Cómo llegar</strong>
|
||||
<p>Metro L5 — Horta<br>Bus V19, 45, 102</p>
|
||||
<p>Metro: L3 (verde), parada Valldaura; L5 (azul), parada Horta<br>Bus: 102, V21, V23, V25 (Pl. Botticelli); 102, N4, V25 (Av. l'Estatut de Catalunya - Campoamor)</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="contact-map">
|
||||
<iframe
|
||||
src="https://www.openstreetmap.org/export/embed.html?bbox=2.1550%2C41.4380%2C2.1650%2C41.4430&layer=mapnik&marker=41.4405%2C2.1600"
|
||||
src="https://www.openstreetmap.org/export/embed.html?bbox=2.1535%2C41.4332%2C2.1635%2C41.4382&layer=mapnik&marker=41.4357%2C2.1585"
|
||||
width="100%" height="300" style="border:0; border-radius: 12px;"
|
||||
loading="lazy" title="Mapa MAY Studio">
|
||||
loading="lazy" title="Mapa MAY STUDIO">
|
||||
</iframe>
|
||||
</div>
|
||||
</div>
|
||||
@@ -200,8 +201,8 @@
|
||||
<!-- FOOTER -->
|
||||
<footer class="footer">
|
||||
<div class="container footer-inner">
|
||||
<span class="logo">MAY <span>Studio</span></span>
|
||||
<p>© 2026 MAY Studio. Tu peluquería en Horta.</p>
|
||||
<span class="logo">MAY <span>STUDIO</span></span>
|
||||
<p>© 2026 MAY STUDIO. Tu peluquería en Horta.</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -404,6 +405,7 @@
|
||||
|
||||
// No lock to category anymore - services from different categories can be selected
|
||||
updateServiceSummary();
|
||||
loadMonthAvailability();
|
||||
|
||||
if (selectedDate) {
|
||||
selectedHora = null;
|
||||
@@ -435,6 +437,8 @@
|
||||
let selectedDate = null;
|
||||
let selectedHora = null;
|
||||
let availableSlotsForDate = []; // array de "HH:mm" devueltos por EA
|
||||
let unavailableDays = new Set(); // días "YYYY-MM-DD" del mes sin ningún hueco (según EA)
|
||||
let monthAvailSeq = 0; // para descartar respuestas que llegan tarde
|
||||
|
||||
const MONTH_NAMES = ['Enero','Febrero','Marzo','Abril','Mayo','Junio','Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'];
|
||||
|
||||
@@ -506,12 +510,35 @@
|
||||
btn.textContent = d;
|
||||
btn.className = 'cal-day';
|
||||
if (date < today || dow === 0) { btn.disabled = true; btn.classList.add('cal-disabled'); }
|
||||
if (unavailableDays.has(dateStr)) { btn.disabled = true; btn.classList.add('cal-disabled'); }
|
||||
if (dateStr === selectedDate) btn.classList.add('cal-selected');
|
||||
btn.addEventListener('click', () => selectDay(dateStr, dow));
|
||||
grid.appendChild(btn);
|
||||
}
|
||||
}
|
||||
|
||||
// Pide al servidor los días del mes visible sin ningún hueco libre para el
|
||||
// servicio principal y los deshabilita en el calendario. Si la petición
|
||||
// falla, los días quedan clicables y el aviso sale al seleccionar el día.
|
||||
async function loadMonthAvailability() {
|
||||
const seq = ++monthAvailSeq;
|
||||
unavailableDays = new Set();
|
||||
renderCalendar();
|
||||
const serviceId = getPrimaryServiceId();
|
||||
if (!serviceId) return;
|
||||
try {
|
||||
const month = calYear + '-' + pad(calMonth + 1);
|
||||
const res = await fetch('/api/month-availability?month=' + month + '&serviceId=' + serviceId);
|
||||
if (!res.ok) return;
|
||||
const data = await res.json();
|
||||
if (seq !== monthAvailSeq) return; // ya se pidió otro mes u otro servicio
|
||||
unavailableDays = new Set(data.unavailableDays || []);
|
||||
renderCalendar();
|
||||
} catch (e) {
|
||||
console.warn('No se pudo cargar la disponibilidad del mes');
|
||||
}
|
||||
}
|
||||
|
||||
function selectDay(dateStr, dow) {
|
||||
selectedDate = dateStr;
|
||||
selectedHora = null;
|
||||
@@ -606,14 +633,14 @@
|
||||
if (calYear === now.getFullYear() && calMonth === now.getMonth()) return;
|
||||
calMonth--;
|
||||
if (calMonth < 0) { calMonth = 11; calYear--; }
|
||||
renderCalendar();
|
||||
loadMonthAvailability();
|
||||
hideSlots();
|
||||
});
|
||||
|
||||
document.getElementById('cal-next').addEventListener('click', () => {
|
||||
calMonth++;
|
||||
if (calMonth > 11) { calMonth = 0; calYear++; }
|
||||
renderCalendar();
|
||||
loadMonthAvailability();
|
||||
hideSlots();
|
||||
});
|
||||
|
||||
@@ -632,10 +659,19 @@
|
||||
}
|
||||
|
||||
function initBookingForm() {
|
||||
document.getElementById('booking-form').addEventListener('submit', async function(e) {
|
||||
const form = document.getElementById('booking-form');
|
||||
const submit = document.getElementById('booking-submit');
|
||||
|
||||
// El botón de reserva solo se activa con nombre, apellidos y teléfono
|
||||
// rellenos; el email es opcional (hay clientes que no tienen).
|
||||
function updateSubmitState() {
|
||||
submit.disabled = !(form.nombre.value.trim() && form.apellidos.value.trim() && form.telefono.value.trim());
|
||||
}
|
||||
form.addEventListener('input', updateSubmitState);
|
||||
updateSubmitState();
|
||||
|
||||
form.addEventListener('submit', async function(e) {
|
||||
e.preventDefault();
|
||||
const form = e.target;
|
||||
const submit = document.getElementById('booking-submit');
|
||||
const result = document.getElementById('booking-result');
|
||||
|
||||
if (selectedServices.length === 0) { alert('Selecciona al menos un servicio'); return; }
|
||||
@@ -646,8 +682,8 @@
|
||||
// EasyAppointments exige nombre y apellido al crear el cliente.
|
||||
if (!nombre || !apellidos) { alert('Escribe tu nombre y tus apellidos'); return; }
|
||||
|
||||
const email = form.email.value.trim();
|
||||
if (!email) { alert('El email es obligatorio'); return; }
|
||||
const telefono = form.telefono.value.trim();
|
||||
if (!telefono) { alert('El teléfono es obligatorio'); return; }
|
||||
|
||||
submit.disabled = true;
|
||||
submit.textContent = 'Enviando…';
|
||||
@@ -659,8 +695,8 @@
|
||||
const payload = {
|
||||
nombre: nombre,
|
||||
apellidos: apellidos,
|
||||
email: email,
|
||||
telefono: form.telefono.value.trim(),
|
||||
email: form.email.value.trim(),
|
||||
telefono: telefono,
|
||||
mensaje: form.mensaje.value.trim(),
|
||||
serviceIds: selectedServices.map(s => s.id).filter(Boolean),
|
||||
date: selectedDate,
|
||||
@@ -695,8 +731,8 @@
|
||||
}
|
||||
|
||||
result.style.display = 'block';
|
||||
submit.disabled = false;
|
||||
submit.textContent = 'Confirmar reserva';
|
||||
updateSubmitState();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user