cambios propuestos por dru

This commit is contained in:
2026-07-12 10:47:25 +02:00
parent 6400485b6d
commit e40536023d
5 changed files with 397 additions and 43 deletions
+66 -30
View File
@@ -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 &amp; 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>&copy; 2026 MAY Studio. Tu peluquería en Horta.</p>
<span class="logo">MAY <span>STUDIO</span></span>
<p>&copy; 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();
});
}
+5
View File
@@ -72,6 +72,11 @@ img { max-width: 100%; display: block; }
font-size: 0.85rem;
}
.btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
/* ============ HERO ============ */
.hero {
position: relative;