Unterschiede zwischen Oliventrester und nativem Olivenöl extra

Wie Sie wahrscheinlich schon wissen, ist die Olive ein sehr vielseitiges Produkt. In der Tat gibt es zahlreiche Sorten, aus denen exquisite Produkte entstehen. Erstens können wir die Frucht essen, sorgfältig behandelt und nach einem traditionellen Verfahren zubereitet, sogar bei vielen Familien im eigenen Haus, wobei köstliche Aromen entstehen, die die Olive zur Geltung bringen. Daraus lässt sich auch eines der wichtigsten Produkte des Mittelmeerraums gewinnen, das native Olivenöl extra, nicht nur eine ausgezeichnete Zutat zum Kochen, sondern auch eine Quelle der Gesundheit. Aber auch Oliventrester wird aus der Olive gewonnen, ein weiteres Öl, das für viele unbekannt ist, wohingegen andere es schon ein Leben lang verwenden. Wenn also in beiden Fällen das Öl von der Olive stammt, wie genau unterscheiden sie sich dann?

Um die Unterschiede zwischen Trester und Olivenöl zu kennen, sollten Sie wissen

  1. Wie diese Öle hergestellt werden.
  2. Welches gesünder ist.
  3. Was die Verwendungszwecke von beiden sind.


1. Wie werden natives Olivenöl extra und Oliventrester hergestellt

Verfahren zur Herstellung von nativem Olivenöl extra.

Natives Olivenöl extra entsteht einerseits durch die Kaltextraktion des Olivensaftes, die ausschließlich durch physikalisch-mechanische Verfahren erfolgt. Wichtig ist es, klarzustellen, dass die Ernte dieser Olive (ob manuell oder maschinell) in der Regel zwischen den Monaten Oktober und Dezember stattfindet, um sicherzustellen, dass die Frucht alle ihre Eigenschaften behält. Nach der Ernte werden die Oliven in der Ölmühle gelagert, um den Verlust ihrer Qualitäten und die Lichteinwirkung zu verhindern, wobei die verschiedenen Qualitäten getrennt werden. Als nächstes werden die Oliven von Staub und Blättern gereinigt und dann gemahlen. Und die aus dieser Vermahlung erhaltene Masse durchläuft zwei Trennungsvorgänge durch Zentrifugation, mit denen wir schließlich dieses exquisite Produkt erhalten, dessen Säuregehalt bei der Qualitätsprüfung unter oder gleich 0,8º sein muss. Wenn Sie auf der Suche nach einem hochwertigen nativen Olivenöl extra sind, haben Sie wahrscheinlich schon bemerkt, dass auf dem Etikett angegeben ist, dass die Extraktion kalt erfolgt ist. Und dieser Prozess der “Kaltextraktion” zur Erzielung der besten Produktqualität bedeutet, bei der Herstellung des Öls wurde die Temperatur zwischen 17ºC und 21ºC gehalten.

Verfahren zur Herstellung von Oliventresteröl.

Andererseits ist Tresteröl das Öl, das aus den Olivenabfällen des vorherigen Prozesses stammt: aus dem Fett und den Rückständen der Olivenkerne und -schalen. Obwohl es bis zu drei Arten der Verarbeitung von Trester gibt, interessiert uns hier diejenige, die ihn für den Verzehr geeignet macht: die Herstellung von raffiniertem Oliventresteröl. Anders als natives Olivenöl extra muss dieses Tresteröl chemischen Prozessen unterzogen werden, bei denen Lösungsmittel verwendet und die Substanz raffiniert wird, um ein genießbares Produkt mit einem maximalen Säuregehalt von 1,5º zu erhalten. Darüber hinaus wird es bei der Vermarktung mit nativem Olivenöl gemischt, um seinen Geschmack sowie seine positiven Eigenschaften zu verbessern..

2. Welches dieser beiden Olivenöle ist gesünder?

Gesundheitliche Eigenschaften von nativem Olivenöl extra

Ohne zu sehr ins Detail zu gehen, da natives Olivenöl extra ein großartiges Produkt für die Gesundheit ist, das eine eigene Seite verdient, kann man nur sagen, es ist ein Nahrungsmittel, das eine große Menge an Polyphenolen und Hydroxyterpensäuren sowie Squalen, Oleocanthal und Vitaminen (A, E, D und K) enthält, die es zu einem Antioxidans, Entzündungshemmer und antimikrobiellen Mittel machen. Außerdem ist es durch seinen hohen Gehalt an Omega-3-Fettsäuren (oder mehrfach ungesättigten Fettsäuren) hervorragend zur Bekämpfung von Cholesterin geeignet. In der Tat deuten zahlreiche Studien, wie die von PREDIMED, darauf hin, dass es potenzielle Wirkungen gegen Entzündungen, aber auch gegen Krebs, kardiovaskuläre Pathologien, Diabetes, etc. hat. Kurz gesagt, natives Olivenöl extra ist ein gesundes Produkt und eine der besten Fettquellen in unserer Ernährung (wenn wir täglich zwischen 2 und 3 Esslöffel konsumieren), die uns zusammen mit Fetten aus Nüssen täglich bei der Stärkung unserer Knochen hilft und den Blutkreislauf aktiviert.
Unterschiede zwischen Oliventrester und nativem Olivenöl extra

Gesunde Eigenschaften von Oliventresteröl.

Wenn also natives Olivenöl extra und Oliventrester denselben Ursprung haben, wenn sie aus demselben Rohstoff hergestellt werden, sind sie dann gleich gesund? Die Antwort ist nein, aber mit Nuancen. Tatsache ist, dass Oliventrester gesunde Eigenschaften bewahrt, die ihn zu einem besseren Produkt machen im Vergleich zu Sonnenblumenöl und Sonnenblumenöl mit hohem Ölsäuregehalt, die ebenfalls raffiniert sind. Während Sonnenblumenöle auf Nährwertebene nur Sterole und Toposphären enthalten, bewahrt Oliventresteröl als kulinarisches Produkt mehr bioaktive Verbindungen, die der Gesundheit zuträglich sind. Mit anderen Worten: Während raffinierte Öle aus Samen nicht besonders viele Vorteile bieten, ist Oliventresteröl das zweitgesündeste Öl auf dem Markt, das wir konsumieren können. Somit hat es zwar nicht die Vorteile von nativem Olivenöl extra, aber Trester ist ein Öl, das ebenfalls natürliche Antioxidantien wie Vitamin E, Chlorophyll und Karotine enthält. Zudem ist dieses Öl laut Jesús Francisco Rodríguez Huertas, Professor für Physiologie und Direktor des Instituts für Ernährung und Lebensmitteltechnologie an der Universität Granada, reich an Ölsäure, was es unter anderem zu einem Lebensmittel mit antithrombotischen und gefäßerweiternden Eigenschaften macht. Die Verwendung von nativem Olivenöl extra kann jedoch nicht durch Oliventresteröl ersetzt werden.

3. Wofür werden die beiden Öle also empfohlen?

Verwendung von Oliventresteröl

Wie bereits erwähnt, ist Oliventresteröl ein besseres kulinarisches Produkt als Sonnenblumenöl, weshalb es sich zumindest zum Braten eignet, wie die vergleichende Studie der Hauptforscherin des Instituts für Lebensmittelwissenschaft und -technologie und Ernährung (ICTAN) des Spanischen Nationalen Forschungsrats (CSIC), Gloria Márquez, belegt. Tresteröl bewahrt seinen Nährwert dank Elementen in seiner Zusammensetzung wie Squalen und Beta-Sitosterol während einer größeren Anzahl von Frittiervorgängen, während die verschiedenen Sonnenblumenöle, deren Hauptbestandteil Linolsäure ist, eher dazu neigen, sich bei hohen Temperaturen zu verändern. Aus diesem Grund würden wir, wenn Trester verwendet wird, diesen nur zum Braten empfehlen, da hierbei der Ölverbrauch höher ist. Auf der anderen Seite ist Olivenöl, insbesondere natives Olivenöl extra, ein viel gesünderes Produkt und in der Küche zu empfehlen:

Verwendungen von nativem Olivenöl extra

Neben dem Braten mit nativem Olivenöl extra (das größere Vorteile hat), kann dieses kulinarische Produkt zur Zubereitung von sautierten oder gegrillten Speisen, in Eintöpfen und Aufläufen, in Suppen und Cremes, in Gerichten, die im Ofen zubereitet werden, und sogar in Gebäck verwendet werden. Aber um alle seine Eigenschaften zu erhalten, ist der Verzehr von nativem Olivenöl extra kalt noch besser, da man von all seinen gesunden Eigenschaften profitieren kann, sei es als Teil von Dressings und verschiedenen Saucen für Salate und kalte Gerichte, in Gazpachos und Salmorejos oder auf Brotscheiben, einem unbestrittenen Klassiker.

Melden Sie sich für unseren monatlichen Newsletter

Reservar mesa ▲

Reserva tu mesa en Qanat

Selecciona fecha, hora y número de comensales

1
Reserva tu mesa
2
Pagar y confirmar
Reserva tu mesa
Comensales
Fecha
Hora

Selecciona una fecha para ver los horarios disponibles

Tus datos
Deseo mesa compartida
Confirma tu reserva
Comensales
—
Fecha
—
Hora
—
Nombre
—
Email
—
Teléfono
—
Mesa compartida
—
Observaciones
—
Se requiere un depósito para confirmar tu reserva
0.00 €
Reembolsable si cancelas con 24h de antelación
Datos de la tarjeta
Acepto las condiciones de reserva y la política de privacidad
Condiciones de reserva

Reserva y puntualidad
Mantendremos tu mesa reservada durante 15 minutos de cortesía. Si prevés llegar más tarde, te agradeceremos que nos lo comuniques. En caso contrario, no podremos garantizar la disponibilidad de la reserva.

Cancelaciones
Las cancelaciones realizadas con menos de 24 horas de antelación no serán reembolsables en ningún caso.

Edad mínima
El acceso está permitido únicamente a mayores de 14 años.

Mascotas
Las mascotas son bienvenidas en nuestra terraza, siempre que permanezcan limpias, tranquilas, atadas y bajo la supervisión de su responsable, evitando en todo momento molestias al resto de los clientes. Nos reservamos el derecho de asignar la mesa que consideremos más adecuada. Durante la temporada de invierno, te rogamos que nos consultes antes de realizar la reserva.

Código de vestimenta
Agradecemos una vestimenta smart casual: elegante, cómoda e informal.

Convivencia
Te rogamos mantener un ambiente tranquilo, evitando alzar la voz y mostrando respeto tanto hacia los demás clientes como hacia nuestro equipo. Está permitido fumar únicamente en la zona habilitada para ello.

Restricciones alimentarias
Si tienes alguna alergia, intolerancia o restricción alimentaria, te agradeceremos que nos lo comuniques antes de tu llegada. Una vez iniciado el servicio, no podemos garantizar que sea posible realizar modificaciones en el menú.

Con el fin de preservar el ambiente y el bienestar de todos los presentes, nos reservamos el derecho de solicitar el abandono del establecimiento en caso de comportamientos que alteren la convivencia o el normal desarrollo del servicio.

Procesando...

Gestionar reserva

← Volver a reservar
📅
🕐
👥
👤
✉️
📞
⚠️
🥗
📝

🍽️ Selección del menú

Entrantes
Principales
Postres

Modificar reserva

🍽️ Selección del menú

'; }).join(''); var offset = (new Date(flavorCalYear, flavorCalMonth, 1).getDay() + 6) % 7; var dim = new Date(flavorCalYear, flavorCalMonth + 1, 0).getDate(); for (var i = 0; i < offset; i++) h += '
'; var minStr = formatDateLocal(flavorMinDate); var maxStr = formatDateLocal(flavorMaxDate); for (var d = 1; d <= dim; d++) { var date = new Date(flavorCalYear, flavorCalMonth, d); var dateStr = formatDateLocal(date); var isSel = flavorData.date === dateStr; var isToday = date.toDateString() === today.toDateString(); var isPast = dateStr < minStr || dateStr > maxStr; var isClosed = !isPast && flavorOpenDays.indexOf(date.getDay()) === -1; var isBlocked = !isPast && !isClosed && flavorBlockedDates[dateStr]; var cls = 'flavor-cal-day'; if (isPast) cls += ' past'; else if (isClosed || isBlocked) cls += ' closed'; else if (isSel) cls += ' on'; else if (isToday) cls += ' today'; if (isPast || isClosed || isBlocked) { h += '
' + d + '
'; } else { h += ''; } } grid.innerHTML = h; grid.querySelectorAll('.flavor-cal-day[data-date]').forEach(function(b) { b.addEventListener('click', function() { flavorData.date = b.dataset.date; flavorData.time = null; flavorRenderCalendar(); flavorLoadTimeSlots(flavorData.date); }); }); } document.getElementById('flavorCalPrev').addEventListener('click', function() { var now = new Date(); if (flavorCalMonth <= now.getMonth() && flavorCalYear <= now.getFullYear()) return; flavorCalMonth--; if (flavorCalMonth < 0) { flavorCalMonth = 11; flavorCalYear--; } flavorRenderCalendar(); }); document.getElementById('flavorCalNext').addEventListener('click', function() { flavorCalMonth++; if (flavorCalMonth > 11) { flavorCalMonth = 0; flavorCalYear++; } flavorRenderCalendar(); }); // ===================== // TIME SLOTS // ===================== function flavorLoadTimeSlots(dateStr) { var container = document.getElementById('flavorSlots'); var guests = flavorData.guests || 2; container.innerHTML = '

' + flavorI18n.loadingTimes + '

'; fetch(flavorRestUrl + 'restaurants/' + flavorRestaurantId + '/available-slots?date=' + dateStr + '&guests=' + guests) .then(function(r) { return r.json(); }) .then(function(data) { if (data.success && data.data && data.data.length > 0) { var html = ''; data.data.forEach(function(slot) { var timeShort = slot.time.substring(0, 5); if (slot.available) { var cls = 'flavor-slot' + (flavorData.time === timeShort ? ' on' : ''); html += ''; } else { var reasonText = flavorI18n.notAvailable; if (slot.reason === 'capacity') reasonText = flavorI18n.capacityFull; else if (slot.reason === 'max_reservations') reasonText = flavorI18n.maxReservations; else if (slot.reason === 'min_advance') reasonText = flavorI18n.minAdvance; html += ''; } }); container.innerHTML = html; container.querySelectorAll('.flavor-slot:not(.busy)').forEach(function(b) { b.addEventListener('click', function() { flavorData.time = b.dataset.t; container.querySelectorAll('.flavor-slot').forEach(function(s) { s.classList.remove('on'); }); b.classList.add('on'); flavorCheckStep1(); }); }); } else { container.innerHTML = '

' + flavorI18n.noTimesAvailable + '

'; } }) .catch(function() { container.innerHTML = '

' + flavorI18n.errorLoadingTimes + '

'; }); } // ===================== // CHIPS (Guests) // ===================== document.getElementById('flavorChips').addEventListener('click', function(e) { var c = e.target.closest('.flavor-chip'); if (!c) return; flavorData.guests = parseInt(c.dataset.val); document.querySelectorAll('.flavor-chip').forEach(function(x) { x.classList.remove('on'); }); c.classList.add('on'); if (flavorData.date) { flavorData.time = null; flavorLoadTimeSlots(flavorData.date); } flavorCheckStep1(); }); // ===================== // SHARED TABLE TOGGLE // ===================== var sharedToggle = document.getElementById('flavorSharedToggle'); if (sharedToggle) { sharedToggle.addEventListener('click', function() { flavorData.shared = !flavorData.shared; sharedToggle.classList.toggle('on', flavorData.shared); }); } // ===================== // VALIDATIONS // ===================== function flavorCheckStep1() { var hasBooking = !!(flavorData.date && flavorData.time); if (flavorTotalSteps === 2) { // In 2-step mode, step 1 also contains data fields var hasData = ['flavor-first-name','flavor-last-name','flavor-email','flavor-phone'].every(function(id) { return document.getElementById(id).value.trim() !== ''; }); document.getElementById('flavorBtn1Next').disabled = !(hasBooking && hasData); } else { document.getElementById('flavorBtn1Next').disabled = !hasBooking; } } function flavorCheckStep2() { var ok = ['flavor-first-name','flavor-last-name','flavor-email','flavor-phone'].every(function(id) { return document.getElementById(id).value.trim() !== ''; }); var btn2 = document.getElementById('flavorBtn2Next'); if (btn2) btn2.disabled = !ok; } function flavorCheckStep3() { var chk = document.getElementById('flavor-accept-terms'); // El checkbox solo existe si procede; si no está, el botón queda disponible document.getElementById('flavorBtn3Confirm').disabled = chk ? !chk.checked : false; } ['flavor-first-name','flavor-last-name','flavor-email','flavor-phone'].forEach(function(id) { document.getElementById(id).addEventListener('input', function() { flavorCheckStep2(); if (flavorTotalSteps === 2) flavorCheckStep1(); }); }); (function(){ var chk = document.getElementById('flavor-accept-terms'); if (chk) chk.addEventListener('change', flavorCheckStep3); })(); function flavorValidateStep2() { var fn = document.getElementById('flavor-first-name').value.trim(); var ln = document.getElementById('flavor-last-name').value.trim(); var em = document.getElementById('flavor-email').value.trim(); var ph = document.getElementById('flavor-phone').value.trim(); if (!fn) { flavorToast(flavorI18n.nameRequired); return false; } if (!ln) { flavorToast(flavorI18n.lastNameRequired); return false; } if (!em) { flavorToast(flavorI18n.emailRequired); return false; } if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(em)) { flavorToast(flavorI18n.emailInvalid); return false; } if (!ph) { flavorToast(flavorI18n.phoneRequired); return false; } return true; } // ===================== // SUMMARY // ===================== function flavorBuildSummary() { document.getElementById('sumGuests').textContent = flavorData.guests + ' ' + (flavorData.guests === 1 ? flavorI18n.person : flavorI18n.people); if (flavorData.date) { var parts = flavorData.date.split('-'); var d = new Date(parseInt(parts[0]), parseInt(parts[1]) - 1, parseInt(parts[2])); var dn = flavorI18n.dayNames[d.getDay()].toLowerCase(); document.getElementById('sumDate').textContent = dn + ', ' + parseInt(parts[2]) + ' de ' + flavorI18n.months[parseInt(parts[1]) - 1].toLowerCase() + ' ' + parts[0]; } document.getElementById('sumTime').textContent = flavorData.time ? flavorData.time + 'h' : '\u2014'; var fn = document.getElementById('flavor-first-name').value.trim(); var ln = document.getElementById('flavor-last-name').value.trim(); document.getElementById('sumName').textContent = (fn + ' ' + ln).trim() || '\u2014'; document.getElementById('sumEmail').textContent = document.getElementById('flavor-email').value.trim() || '\u2014'; var pre = document.getElementById('flavor-prefix').value; var ph = document.getElementById('flavor-phone').value.trim(); document.getElementById('sumPhone').textContent = ph ? pre + ph : '\u2014'; document.getElementById('sumShared').textContent = flavorData.shared ? flavorI18n.yes : flavorI18n.no; document.getElementById('sumNotes').textContent = document.getElementById('flavor-notes').value.trim() || '\u2014'; var depositAmount = flavorCalculateDeposit(); var depositBox = document.getElementById('flavorDepositBox'); var cardBox = document.getElementById('flavorCardInputBox'); if (depositAmount > 0 && flavorStripeKey) { depositBox.style.display = 'block'; cardBox.style.display = 'block'; document.getElementById('flavorDepAmount').textContent = depositAmount.toFixed(2) + ' \u20AC'; var perPerson = flavorDepositPerPerson > 0 ? (flavorData.guests + ' \u00D7 ' + flavorDepositPerPerson.toFixed(2) + ' \u20AC ' + flavorI18n.perPerson) : ''; document.getElementById('flavorDepSub').textContent = perPerson; document.getElementById('flavor-submit-text').style.display = 'none'; document.getElementById('flavor-submit-text-pay').style.display = 'inline'; } else { depositBox.style.display = 'none'; cardBox.style.display = 'none'; document.getElementById('flavor-submit-text').style.display = 'inline'; document.getElementById('flavor-submit-text-pay').style.display = 'none'; } } // ===================== // NAVIGATION BUTTONS // ===================== document.getElementById('flavorBtn1Next').addEventListener('click', function() { if (!flavorData.guests) { flavorToast(flavorI18n.selectGuests); return; } if (!flavorData.date) { flavorToast(flavorI18n.selectDate); return; } if (!flavorData.time) { flavorToast(flavorI18n.selectTime); return; } if (flavorTotalSteps === 2 && !flavorValidateStep2()) return; flavorGoStep(2); }); var btn2Back = document.getElementById('flavorBtn2Back'); if (btn2Back) btn2Back.addEventListener('click', function() { flavorGoStep(1); }); var btn2Next = document.getElementById('flavorBtn2Next'); if (btn2Next) btn2Next.addEventListener('click', function() { if (!flavorValidateStep2()) return; flavorGoStep(3); }); document.getElementById('flavorBtn3Back').addEventListener('click', function() { flavorGoStep(flavorTotalSteps === 2 ? 1 : 2); }); document.getElementById('flavorBtn3Confirm').addEventListener('click', function() { flavorSubmit(); }); // Stepper click document.querySelectorAll('.flavor-step-ind').forEach(function(el) { el.addEventListener('click', function() { var target = parseInt(el.dataset.step); if (target < flavorStep) flavorGoStep(target); }); }); // ===================== // DEPOSIT & STRIPE // ===================== function flavorCalculateDeposit() { if (!flavorRequireDeposit) return 0; return flavorDepositPerReservation + (flavorDepositPerPerson * (flavorData.guests || 0)); } function flavorInitStripe() { var depositAmount = flavorCalculateDeposit(); if (depositAmount > 0 && flavorStripeKey && !flavorStripe) { flavorStripe = Stripe(flavorStripeKey); var elements = flavorStripe.elements({locale: 'es'}); flavorCardElement = elements.create('card', { style: { base: { fontSize: '14px', color: '#1a1a1a', fontFamily: 'Inter, -apple-system, sans-serif', '::placeholder': { color: '#c0c0c0' } }, invalid: { color: '#dc2626' } } }); flavorCardElement.mount('#flavor-card-element'); flavorCardElement.on('change', function(event) { document.getElementById('flavor-card-errors').textContent = event.error ? event.error.message : ''; }); } } // ===================== // SUBMIT // ===================== function flavorSubmit() { var _chk = document.getElementById('flavor-accept-terms'); if (_chk && !_chk.checked) { flavorToast(flavorI18n.acceptTerms); return; } // In 2-step mode, validate step2 fields before submit if (flavorTotalSteps === 2 && !flavorValidateStep2()) return; var depositAmount = flavorCalculateDeposit(); if (depositAmount > 0 && flavorStripeKey && flavorCardElement) { flavorSubmitWithPayment(); } else { flavorSubmitWithoutPayment(); } } function flavorGetPostData() { var prefix = document.getElementById('flavor-prefix').value; var phone = document.getElementById('flavor-phone').value.trim(); return { restaurant_id: flavorRestaurantId, shortcode_key: flavorShortcodeKey, guests: flavorData.guests, reservation_date: flavorData.date, reservation_time: flavorData.time, first_name: document.getElementById('flavor-first-name').value, last_name: document.getElementById('flavor-last-name').value, email: document.getElementById('flavor-email').value, phone: prefix + phone, allergies: document.getElementById('flavor-allergies').value, dietary_restrictions: '', notes: document.getElementById('flavor-notes').value, shared_table: flavorData.shared ? 1 : 0 }; } function flavorSubmitWithoutPayment() { document.querySelector('.flavor-loader').style.display = 'flex'; fetch(flavorRestUrl + 'reservations', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(flavorGetPostData()) }) .then(function(r) { return r.json(); }) .then(function(r) { document.querySelector('.flavor-loader').style.display = 'none'; if (r.success) { flavorShowSuccess(r.reservation.reservation || r.reservation); } else { flavorShowError(r.message || 'Error al crear la reserva'); } }) .catch(function() { document.querySelector('.flavor-loader').style.display = 'none'; flavorShowError(flavorI18n.error); }); } function flavorSubmitWithPayment() { var submitBtn = document.getElementById('flavorBtn3Confirm'); submitBtn.disabled = true; submitBtn.innerHTML = '' + flavorI18n.paymentProcessing + ''; var postData = flavorGetPostData(); var customerName = postData.first_name + ' ' + postData.last_name; var customerEmail = postData.email; fetch(flavorRestUrl + 'payment/create-intent', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ restaurant_id: flavorRestaurantId, guests: flavorData.guests, name: customerName, email: customerEmail }) }) .then(function(resp) { return resp.json(); }) .then(function(paymentData) { if (!paymentData.success) throw new Error(paymentData.message || 'Error al iniciar el pago'); return flavorStripe.confirmCardPayment(paymentData.data.client_secret, { payment_method: { card: flavorCardElement, billing_details: { name: customerName, email: customerEmail } } }).then(function(result) { if (result.error) throw new Error(result.error.message); return result.paymentIntent.id; }); }) .then(function(paymentIntentId) { postData.payment_intent_id = paymentIntentId; postData.deposit_paid = 1; return fetch(flavorRestUrl + 'reservations', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(postData) }); }) .then(function(response) { return response.json(); }) .then(function(r) { if (!r.success) throw new Error(r.message || 'Error al crear la reserva'); submitBtn.disabled = false; flavorShowSuccess(r.reservation.reservation || r.reservation); }) .catch(function(error) { submitBtn.disabled = false; submitBtn.innerHTML = '' + flavorI18n.paymentProcessing + ''; document.getElementById('flavor-card-errors').textContent = error.message; flavorToast(error.message); }); } // ===================== // SUCCESS / ERROR // ===================== // Ejecuta un snippet de tracking pegado por el restaurante desde el backoffice. // El snippet se sirve como
' : ''; var notesHtml = postData.notes && postData.notes.trim() ? '
' + flavorI18n.notes + ' ' + flavorEscapeHtml(postData.notes) + '
' : ''; var depositHtml = ''; var depositAmount = flavorCalculateDeposit(); if (depositAmount > 0) { depositHtml = '
\uD83D\uDCB3 ' + flavorI18n.depositPaid + ' ' + depositAmount.toFixed(2) + ' \u20AC
'; } flavorContainer.innerHTML = '
' + '
\u2713
' + '

' + flavorI18n.reservationConfirmed + '

' + '

' + flavorI18n.reservationSuccess + '

' + '
' + code + '
' + '
' + '
' + flavorI18n.date + ' ' + dateStr + '
' + '
' + flavorI18n.time + ' ' + flavorData.time + '
' + '
' + flavorI18n.guests + ' ' + flavorData.guests + ' ' + flavorI18n.people + '
' + '
' + flavorI18n.name + ' ' + flavorEscapeHtml(postData.first_name) + ' ' + flavorEscapeHtml(postData.last_name) + '
' + '
' + flavorI18n.email + ' ' + flavorEscapeHtml(postData.email) + '
' + '
' + flavorI18n.phone + ' ' + flavorEscapeHtml(postData.phone) + '
' + '
' + flavorI18n.sharedTable + ' ' + shared + '
' + allergiesHtml + notesHtml + depositHtml + '
' + '

' + flavorI18n.receiveEmail + '

' + '' + '
'; // Disparar snippet de tracking "reserva creada" (Meta Pixel, GA, etc. según lo que haya configurado el restaurante). flavorRunTrackingSnippet('flavor-tracking-reservation'); // Si el depósito ya se ha cobrado en el mismo flujo (Stripe Elements dentro del form), el evento de pago // también corresponde ahora; el retorno de Stripe con ?payment=success cubre el otro caso (Checkout externo). if (depositAmount > 0) { flavorRunTrackingSnippet('flavor-tracking-payment'); } } function flavorShowError(message) { flavorContainer.innerHTML = '
' + '
\u2717
' + '

' + flavorI18n.error + '

' + '

' + message + '

' + '' + '
'; } // ===================== // TOAST // ===================== function flavorToast(message, type) { type = type || 'warning'; var existing = document.querySelector('.flavor-toast-modal'); var existingOverlay = document.querySelector('.flavor-toast-overlay'); if (existing) existing.remove(); if (existingOverlay) existingOverlay.remove(); var overlay = document.createElement('div'); overlay.className = 'flavor-toast-overlay'; document.body.appendChild(overlay); var toast = document.createElement('div'); toast.className = 'flavor-toast-modal'; toast.innerHTML = '
' + message + '
'; document.body.appendChild(toast); function closeToast() { toast.classList.remove('show'); overlay.classList.remove('show'); setTimeout(function() { toast.remove(); overlay.remove(); }, 250); } overlay.onclick = closeToast; setTimeout(function() { overlay.classList.add('show'); toast.classList.add('show'); }, 10); setTimeout(closeToast, 2500); } // ===================== // BLOCKED DATES & INIT // ===================== fetch(flavorRestUrl + 'restaurants/' + flavorRestaurantId + '/blocked-dates') .then(function(r) { return r.json(); }) .then(function(data) { if (data.success && data.data) { flavorBlockedDates = data.data; flavorRenderCalendar(); flavorSelectFirstAvailableDate(); } }) .catch(function() { flavorSelectFirstAvailableDate(); }); function flavorSelectFirstAvailableDate() { var today = new Date(); today.setHours(0,0,0,0); for (var i = 0; i <= flavorMaxAdvanceDays; i++) { var check = new Date(today); check.setDate(today.getDate() + i); var dateStr = formatDateLocal(check); if (flavorOpenDays.indexOf(check.getDay()) === -1) continue; if (flavorBlockedDates[dateStr]) continue; if (i === 0) { var hoursLeft = 24 - new Date().getHours(); if (hoursLeft < flavorMinAdvanceHours) continue; } flavorSelectDate(dateStr); return; } } function flavorSelectDate(dateStr) { flavorData.date = dateStr; flavorData.time = null; flavorRenderCalendar(); flavorLoadTimeSlots(dateStr); } // ===================== // GESTION DE RESERVAS // ===================== var flavorCurrentReservation = null; function flavorShowManage() { document.querySelectorAll('.flavor-panel').forEach(function(s) { s.style.display = 'none'; }); document.querySelector('.flavor-stepper').style.display = 'none'; document.querySelector('.flavor-manage-view').style.display = 'block'; document.querySelector('.flavor-manage-search').style.display = 'block'; document.querySelector('.flavor-manage-result').style.display = 'none'; document.querySelector('.flavor-manage-modify').style.display = 'none'; } function flavorHideManage() { document.querySelector('.flavor-manage-view').style.display = 'none'; document.querySelectorAll('.flavor-panel').forEach(function(s) { s.style.display = 'none'; }); document.getElementById('flavorPanel1').style.display = 'block'; document.getElementById('flavorPanel1').classList.add('active'); document.querySelector('.flavor-stepper').style.display = 'flex'; flavorStep = 1; flavorUpdateStepper(); flavorCurrentReservation = null; } function flavorManageTab(tab) { document.querySelectorAll('.flavor-manage-tab').forEach(function(t) { t.classList.remove('active'); }); document.querySelectorAll('.flavor-manage-tab-content').forEach(function(c) { c.classList.remove('active'); }); document.querySelector('.flavor-manage-tab-content[data-tab="' + tab + '"]').classList.add('active'); event.target.classList.add('active'); } function flavorSearchByCode() { var code = document.getElementById('flavor-manage-code').value.trim(); if (!code) { flavorToast(flavorI18n.enterCode); return; } flavorSearchReservation({ code: code }); } function flavorSearchByData() { var firstName = document.getElementById('flavor-manage-firstname').value.trim(); var lastName = document.getElementById('flavor-manage-lastname').value.trim(); var phone = document.getElementById('flavor-manage-phone').value.trim(); var date = document.getElementById('flavor-manage-date').value; var time = document.getElementById('flavor-manage-time').value; if (!firstName) { flavorToast(flavorI18n.enterName); return; } if (!lastName) { flavorToast(flavorI18n.enterLastName); return; } if (!phone) { flavorToast(flavorI18n.enterPhone); return; } if (!date) { flavorToast(flavorI18n.enterDate); return; } if (!time) { flavorToast(flavorI18n.enterTime); return; } flavorSearchReservation({ first_name: firstName, last_name: lastName, phone: phone, date: date, time: time + ':00' }); } function flavorSearchReservation(params) { document.querySelector('.flavor-loader').style.display = 'flex'; var url = flavorRestUrl + 'reservations/search?restaurant_id=' + flavorRestaurantId; if (params.code) { url += '&code=' + encodeURIComponent(params.code); } else { url += '&first_name=' + encodeURIComponent(params.first_name); url += '&last_name=' + encodeURIComponent(params.last_name); url += '&phone=' + encodeURIComponent(params.phone); url += '&date=' + encodeURIComponent(params.date); url += '&time=' + encodeURIComponent(params.time); } fetch(url) .then(function(r) { return r.json(); }) .then(function(data) { document.querySelector('.flavor-loader').style.display = 'none'; if (data.success && data.data) { flavorCurrentReservation = data.data; flavorShowReservationResult(data.data); } else { flavorToast(data.message || flavorI18n.reservationNotFound, 'error'); } }) .catch(function() { document.querySelector('.flavor-loader').style.display = 'none'; flavorToast(flavorI18n.searchError, 'error'); }); } function flavorShowReservationResult(res) { document.querySelector('.flavor-manage-search').style.display = 'none'; document.querySelector('.flavor-manage-result').style.display = 'block'; document.querySelector('.flavor-manage-modify').style.display = 'none'; var dateParts = res.reservation_date.split('-'); var dateStr = dateParts[2] + '/' + dateParts[1] + '/' + dateParts[0]; var statusText = flavorI18n.confirmed, statusClass = 'confirmed'; if (res.status === 'pending') { statusText = flavorI18n.pending; statusClass = 'pending'; } if (res.status === 'cancelled') { statusText = flavorI18n.cancelled; statusClass = 'cancelled'; } document.querySelector('.flavor-reservation-code').textContent = res.reservation_code; document.querySelector('.flavor-reservation-status').textContent = statusText; document.querySelector('.flavor-reservation-status').className = 'flavor-reservation-status ' + statusClass; document.querySelector('.flavor-reservation-date').textContent = dateStr; document.querySelector('.flavor-reservation-time').textContent = res.reservation_time.substring(0, 5); document.querySelector('.flavor-reservation-guests').textContent = res.guests + ' ' + flavorI18n.people; document.querySelector('.flavor-reservation-name').textContent = res.first_name + ' ' + res.last_name; document.querySelector('.flavor-reservation-email').textContent = res.email || ''; document.querySelector('.flavor-reservation-phone').textContent = res.phone || ''; var allergiesRow = document.querySelector('.flavor-reservation-allergies'); if (res.allergies && res.allergies.trim()) { allergiesRow.style.display = 'flex'; document.querySelector('.flavor-reservation-allergies-text').textContent = res.allergies; } else { allergiesRow.style.display = 'none'; } var dietaryRow = document.querySelector('.flavor-reservation-dietary'); if (res.dietary_restrictions && res.dietary_restrictions.trim()) { dietaryRow.style.display = 'flex'; document.querySelector('.flavor-reservation-dietary-text').textContent = res.dietary_restrictions; } else { dietaryRow.style.display = 'none'; } var notesRow = document.querySelector('.flavor-reservation-notes'); if (res.notes && res.notes.trim()) { notesRow.style.display = 'flex'; document.querySelector('.flavor-reservation-notes-text').textContent = res.notes; } else { notesRow.style.display = 'none'; } var menuSection = document.querySelector('.flavor-reservation-menu'); var hasMenu = (res.menu_starters && res.menu_starters.trim()) || (res.menu_mains && res.menu_mains.trim()) || (res.menu_desserts && res.menu_desserts.trim()); if (hasMenu) { menuSection.style.display = 'block'; var st = document.querySelector('.flavor-reservation-starters'); if (res.menu_starters && res.menu_starters.trim()) { st.style.display = 'block'; document.querySelector('.flavor-reservation-starters-text').textContent = res.menu_starters; } else { st.style.display = 'none'; } var mn = document.querySelector('.flavor-reservation-mains'); if (res.menu_mains && res.menu_mains.trim()) { mn.style.display = 'block'; document.querySelector('.flavor-reservation-mains-text').textContent = res.menu_mains; } else { mn.style.display = 'none'; } var ds = document.querySelector('.flavor-reservation-desserts'); if (res.menu_desserts && res.menu_desserts.trim()) { ds.style.display = 'block'; document.querySelector('.flavor-reservation-desserts-text').textContent = res.menu_desserts; } else { ds.style.display = 'none'; } } else { menuSection.style.display = 'none'; } var actionsDiv = document.querySelector('.flavor-manage-actions'); if (res.status === 'cancelled') { actionsDiv.style.display = 'none'; } else { actionsDiv.style.display = 'flex'; } } function flavorShowModify() { document.querySelector('.flavor-manage-result').style.display = 'none'; document.querySelector('.flavor-manage-modify').style.display = 'block'; var res = flavorCurrentReservation; var select = document.getElementById('flavor-modify-guests'); select.innerHTML = ''; for (var i = flavorMinGuests; i <= Math.min(flavorMaxGuests, 12); i++) { var opt = document.createElement('option'); opt.value = i; opt.textContent = i + ' ' + (i === 1 ? flavorI18n.person : flavorI18n.people); if (i === parseInt(res.guests)) opt.selected = true; select.appendChild(opt); } document.getElementById('flavor-modify-date').value = res.reservation_date; document.getElementById('flavor-modify-first-name').value = res.first_name || ''; document.getElementById('flavor-modify-last-name').value = res.last_name || ''; document.getElementById('flavor-modify-email').value = res.email || ''; document.getElementById('flavor-modify-phone').value = res.phone || ''; document.getElementById('flavor-modify-allergies').value = res.allergies || ''; document.getElementById('flavor-modify-dietary').value = res.dietary_restrictions || ''; document.getElementById('flavor-modify-notes').value = res.notes || ''; document.getElementById('flavor-modify-shared-table').checked = parseInt(res.shared_table) === 1; document.getElementById('flavor-modify-starters').value = res.menu_starters || ''; document.getElementById('flavor-modify-mains').value = res.menu_mains || ''; document.getElementById('flavor-modify-desserts').value = res.menu_desserts || ''; flavorLoadModifyTimeSlots(res.reservation_date); } function flavorLoadModifyTimeSlots(date) { var select = document.getElementById('flavor-modify-time'); select.innerHTML = ''; var guests = document.getElementById('flavor-modify-guests').value; fetch(flavorRestUrl + 'restaurants/' + flavorRestaurantId + '/available-slots?date=' + date + '&guests=' + guests) .then(function(r) { return r.json(); }) .then(function(data) { select.innerHTML = ''; if (data.success && data.data && data.data.length > 0) { data.data.forEach(function(slot) { if (slot.available) { var opt = document.createElement('option'); opt.value = slot.time.substring(0, 5); opt.textContent = slot.time.substring(0, 5); select.appendChild(opt); } }); var currentTime = flavorCurrentReservation.reservation_time; var hasCurrentTime = false; for (var i = 0; i < select.options.length; i++) { if (select.options[i].value === currentTime) { hasCurrentTime = true; break; } } if (!hasCurrentTime && date === flavorCurrentReservation.reservation_date) { var opt = document.createElement('option'); opt.value = currentTime; opt.textContent = currentTime.substring(0, 5) + ' ' + flavorI18n.current; opt.selected = true; select.insertBefore(opt, select.firstChild); } } else { select.innerHTML = ''; } }) .catch(function() { select.innerHTML = ''; }); } document.getElementById('flavor-modify-date').addEventListener('change', function() { flavorLoadModifyTimeSlots(this.value); }); function flavorBackToResult() { document.querySelector('.flavor-manage-modify').style.display = 'none'; document.querySelector('.flavor-manage-result').style.display = 'block'; } function flavorSaveModification() { if (!flavorCurrentReservation) return; var newTime = document.getElementById('flavor-modify-time').value; if (!newTime) { flavorToast(flavorI18n.selectTimeFirst); return; } document.querySelector('.flavor-loader').style.display = 'flex'; fetch(flavorRestUrl + 'reservations/' + flavorCurrentReservation.id + '/modify', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ guests: parseInt(document.getElementById('flavor-modify-guests').value), reservation_date: document.getElementById('flavor-modify-date').value, reservation_time: newTime, first_name: document.getElementById('flavor-modify-first-name').value, last_name: document.getElementById('flavor-modify-last-name').value, email: document.getElementById('flavor-modify-email').value, phone: document.getElementById('flavor-modify-phone').value, allergies: document.getElementById('flavor-modify-allergies').value, dietary_restrictions: document.getElementById('flavor-modify-dietary').value, notes: document.getElementById('flavor-modify-notes').value, shared_table: document.getElementById('flavor-modify-shared-table').checked ? 1 : 0, menu_starters: document.getElementById('flavor-modify-starters').value, menu_mains: document.getElementById('flavor-modify-mains').value, menu_desserts: document.getElementById('flavor-modify-desserts').value }) }) .then(function(r) { return r.json(); }) .then(function(data) { document.querySelector('.flavor-loader').style.display = 'none'; if (data.success) { flavorCurrentReservation = data.data; flavorShowReservationResult(data.data); flavorToast(flavorI18n.modifySuccess, 'success'); } else { flavorToast(data.message || flavorI18n.modifyError, 'error'); } }) .catch(function() { document.querySelector('.flavor-loader').style.display = 'none'; flavorToast(flavorI18n.modifyError, 'error'); }); } function flavorCancelReservation() { if (!flavorCurrentReservation) return; if (!confirm(flavorI18n.cancelConfirm)) return; document.querySelector('.flavor-loader').style.display = 'flex'; fetch(flavorRestUrl + 'reservations/' + flavorCurrentReservation.id + '/cancel-public', { method: 'PUT', headers: { 'Content-Type': 'application/json' } }) .then(function(r) { return r.json(); }) .then(function(data) { document.querySelector('.flavor-loader').style.display = 'none'; if (data.success) { flavorCurrentReservation.status = 'cancelled'; flavorShowReservationResult(flavorCurrentReservation); flavorToast(flavorI18n.cancelSuccess, 'success'); } else { flavorToast(data.message || flavorI18n.cancelError, 'error'); } }) .catch(function() { document.querySelector('.flavor-loader').style.display = 'none'; flavorToast(flavorI18n.cancelError, 'error'); }); } // == Init == flavorRenderCalendar(); flavorCheckStep1(); // Detect manage_code in URL (function() { var urlParams = new URLSearchParams(window.location.search); var manageCode = urlParams.get('manage_code'); if (manageCode || window.location.hash === '#manage') { flavorShowManage(); setTimeout(function() { var el = document.getElementById('manage'); if (el) { window.scrollTo({ top: window.pageYOffset + el.getBoundingClientRect().top - 20, behavior: 'smooth' }); } }, 500); if (manageCode) { document.getElementById('flavor-manage-code').value = manageCode; setTimeout(function() { flavorSearchReservation({ code: manageCode }); }, 300); } } })(); // Detectar retorno de Stripe Checkout externo con ?payment=success (link de pago enviado por email). // Dispara el snippet de tracking de pago del depósito. Se ejecuta una sola vez y limpiamos el // parámetro de la URL para que un F5 no vuelva a disparar el evento. (function() { try { var params = new URLSearchParams(window.location.search); if (params.get('payment') === 'success') { flavorRunTrackingSnippet('flavor-tracking-payment'); // Limpiar los parámetros payment=success&code=... de la URL sin recargar if (window.history && window.history.replaceState) { params.delete('payment'); params.delete('code'); var qs = params.toString(); var cleanUrl = window.location.pathname + (qs ? '?' + qs : '') + window.location.hash; window.history.replaceState({}, document.title, cleanUrl); } } } catch (e) {} })();
1
Reserva la teva taula
2
Pagar i confirmar
Reserva la teva taula
Comensals
Data
Hora

Selecciona una data per veure els horaris disponibles

Les teves dades
Desitjo taula compartida
Confirma la teva reserva
Comensals
—
Data
—
Hora
—
Nom
—
Email
—
Telèfon
—
Taula compartida
—
Observacions
—
Es requereix un dipòsit per confirmar la teva reserva
0.00 €
Reembolsable si cancelas con 24h de antelación
Dades de la targeta
Accepto les condicions de reserva i la política de privacitat
Condiciones de reserva

Reserva y puntualidad
Mantendremos tu mesa reservada durante 15 minutos de cortesía. Si prevés llegar más tarde, te agradeceremos que nos lo comuniques. En caso contrario, no podremos garantizar la disponibilidad de la reserva.

Cancelaciones
Las cancelaciones realizadas con menos de 24 horas de antelación no serán reembolsables en ningún caso.

Edad mínima
El acceso está permitido únicamente a mayores de 14 años.

Mascotas
Las mascotas son bienvenidas en nuestra terraza, siempre que permanezcan limpias, tranquilas, atadas y bajo la supervisión de su responsable, evitando en todo momento molestias al resto de los clientes. Nos reservamos el derecho de asignar la mesa que consideremos más adecuada. Durante la temporada de invierno, te rogamos que nos consultes antes de realizar la reserva.

Código de vestimenta
Agradecemos una vestimenta smart casual: elegante, cómoda e informal.

Convivencia
Te rogamos mantener un ambiente tranquilo, evitando alzar la voz y mostrando respeto tanto hacia los demás clientes como hacia nuestro equipo. Está permitido fumar únicamente en la zona habilitada para ello.

Restricciones alimentarias
Si tienes alguna alergia, intolerancia o restricción alimentaria, te agradeceremos que nos lo comuniques antes de tu llegada. Una vez iniciado el servicio, no podemos garantizar que sea posible realizar modificaciones en el menú.

Con el fin de preservar el ambiente y el bienestar de todos los presentes, nos reservamos el derecho de solicitar el abandono del establecimiento en caso de comportamientos que alteren la convivencia o el normal desarrollo del servicio.

Processant...

Gestionar reserva

← Tornar a reservar
📅
🕐
👥
👤
✉️
📞
⚠️
🥗
📝

🍽️ Selecció del menú

Entrants
Principals
Postres

Modificar reserva

🍽️ Selecció del menú

'; }).join(''); var offset = (new Date(flavorCalYear, flavorCalMonth, 1).getDay() + 6) % 7; var dim = new Date(flavorCalYear, flavorCalMonth + 1, 0).getDate(); for (var i = 0; i < offset; i++) h += '
'; var minStr = formatDateLocal(flavorMinDate); var maxStr = formatDateLocal(flavorMaxDate); for (var d = 1; d <= dim; d++) { var date = new Date(flavorCalYear, flavorCalMonth, d); var dateStr = formatDateLocal(date); var isSel = flavorData.date === dateStr; var isToday = date.toDateString() === today.toDateString(); var isPast = dateStr < minStr || dateStr > maxStr; var isClosed = !isPast && flavorOpenDays.indexOf(date.getDay()) === -1; var isBlocked = !isPast && !isClosed && flavorBlockedDates[dateStr]; var cls = 'flavor-cal-day'; if (isPast) cls += ' past'; else if (isClosed || isBlocked) cls += ' closed'; else if (isSel) cls += ' on'; else if (isToday) cls += ' today'; if (isPast || isClosed || isBlocked) { h += '
' + d + '
'; } else { h += ''; } } grid.innerHTML = h; grid.querySelectorAll('.flavor-cal-day[data-date]').forEach(function(b) { b.addEventListener('click', function() { flavorData.date = b.dataset.date; flavorData.time = null; flavorRenderCalendar(); flavorLoadTimeSlots(flavorData.date); }); }); } document.getElementById('flavorCalPrev').addEventListener('click', function() { var now = new Date(); if (flavorCalMonth <= now.getMonth() && flavorCalYear <= now.getFullYear()) return; flavorCalMonth--; if (flavorCalMonth < 0) { flavorCalMonth = 11; flavorCalYear--; } flavorRenderCalendar(); }); document.getElementById('flavorCalNext').addEventListener('click', function() { flavorCalMonth++; if (flavorCalMonth > 11) { flavorCalMonth = 0; flavorCalYear++; } flavorRenderCalendar(); }); // ===================== // TIME SLOTS // ===================== function flavorLoadTimeSlots(dateStr) { var container = document.getElementById('flavorSlots'); var guests = flavorData.guests || 2; container.innerHTML = '

' + flavorI18n.loadingTimes + '

'; fetch(flavorRestUrl + 'restaurants/' + flavorRestaurantId + '/available-slots?date=' + dateStr + '&guests=' + guests) .then(function(r) { return r.json(); }) .then(function(data) { if (data.success && data.data && data.data.length > 0) { var html = ''; data.data.forEach(function(slot) { var timeShort = slot.time.substring(0, 5); if (slot.available) { var cls = 'flavor-slot' + (flavorData.time === timeShort ? ' on' : ''); html += ''; } else { var reasonText = flavorI18n.notAvailable; if (slot.reason === 'capacity') reasonText = flavorI18n.capacityFull; else if (slot.reason === 'max_reservations') reasonText = flavorI18n.maxReservations; else if (slot.reason === 'min_advance') reasonText = flavorI18n.minAdvance; html += ''; } }); container.innerHTML = html; container.querySelectorAll('.flavor-slot:not(.busy)').forEach(function(b) { b.addEventListener('click', function() { flavorData.time = b.dataset.t; container.querySelectorAll('.flavor-slot').forEach(function(s) { s.classList.remove('on'); }); b.classList.add('on'); flavorCheckStep1(); }); }); } else { container.innerHTML = '

' + flavorI18n.noTimesAvailable + '

'; } }) .catch(function() { container.innerHTML = '

' + flavorI18n.errorLoadingTimes + '

'; }); } // ===================== // CHIPS (Guests) // ===================== document.getElementById('flavorChips').addEventListener('click', function(e) { var c = e.target.closest('.flavor-chip'); if (!c) return; flavorData.guests = parseInt(c.dataset.val); document.querySelectorAll('.flavor-chip').forEach(function(x) { x.classList.remove('on'); }); c.classList.add('on'); if (flavorData.date) { flavorData.time = null; flavorLoadTimeSlots(flavorData.date); } flavorCheckStep1(); }); // ===================== // SHARED TABLE TOGGLE // ===================== var sharedToggle = document.getElementById('flavorSharedToggle'); if (sharedToggle) { sharedToggle.addEventListener('click', function() { flavorData.shared = !flavorData.shared; sharedToggle.classList.toggle('on', flavorData.shared); }); } // ===================== // VALIDATIONS // ===================== function flavorCheckStep1() { var hasBooking = !!(flavorData.date && flavorData.time); if (flavorTotalSteps === 2) { // In 2-step mode, step 1 also contains data fields var hasData = ['flavor-first-name','flavor-last-name','flavor-email','flavor-phone'].every(function(id) { return document.getElementById(id).value.trim() !== ''; }); document.getElementById('flavorBtn1Next').disabled = !(hasBooking && hasData); } else { document.getElementById('flavorBtn1Next').disabled = !hasBooking; } } function flavorCheckStep2() { var ok = ['flavor-first-name','flavor-last-name','flavor-email','flavor-phone'].every(function(id) { return document.getElementById(id).value.trim() !== ''; }); var btn2 = document.getElementById('flavorBtn2Next'); if (btn2) btn2.disabled = !ok; } function flavorCheckStep3() { var chk = document.getElementById('flavor-accept-terms'); // El checkbox solo existe si procede; si no está, el botón queda disponible document.getElementById('flavorBtn3Confirm').disabled = chk ? !chk.checked : false; } ['flavor-first-name','flavor-last-name','flavor-email','flavor-phone'].forEach(function(id) { document.getElementById(id).addEventListener('input', function() { flavorCheckStep2(); if (flavorTotalSteps === 2) flavorCheckStep1(); }); }); (function(){ var chk = document.getElementById('flavor-accept-terms'); if (chk) chk.addEventListener('change', flavorCheckStep3); })(); function flavorValidateStep2() { var fn = document.getElementById('flavor-first-name').value.trim(); var ln = document.getElementById('flavor-last-name').value.trim(); var em = document.getElementById('flavor-email').value.trim(); var ph = document.getElementById('flavor-phone').value.trim(); if (!fn) { flavorToast(flavorI18n.nameRequired); return false; } if (!ln) { flavorToast(flavorI18n.lastNameRequired); return false; } if (!em) { flavorToast(flavorI18n.emailRequired); return false; } if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(em)) { flavorToast(flavorI18n.emailInvalid); return false; } if (!ph) { flavorToast(flavorI18n.phoneRequired); return false; } return true; } // ===================== // SUMMARY // ===================== function flavorBuildSummary() { document.getElementById('sumGuests').textContent = flavorData.guests + ' ' + (flavorData.guests === 1 ? flavorI18n.person : flavorI18n.people); if (flavorData.date) { var parts = flavorData.date.split('-'); var d = new Date(parseInt(parts[0]), parseInt(parts[1]) - 1, parseInt(parts[2])); var dn = flavorI18n.dayNames[d.getDay()].toLowerCase(); document.getElementById('sumDate').textContent = dn + ', ' + parseInt(parts[2]) + ' de ' + flavorI18n.months[parseInt(parts[1]) - 1].toLowerCase() + ' ' + parts[0]; } document.getElementById('sumTime').textContent = flavorData.time ? flavorData.time + 'h' : '\u2014'; var fn = document.getElementById('flavor-first-name').value.trim(); var ln = document.getElementById('flavor-last-name').value.trim(); document.getElementById('sumName').textContent = (fn + ' ' + ln).trim() || '\u2014'; document.getElementById('sumEmail').textContent = document.getElementById('flavor-email').value.trim() || '\u2014'; var pre = document.getElementById('flavor-prefix').value; var ph = document.getElementById('flavor-phone').value.trim(); document.getElementById('sumPhone').textContent = ph ? pre + ph : '\u2014'; document.getElementById('sumShared').textContent = flavorData.shared ? flavorI18n.yes : flavorI18n.no; document.getElementById('sumNotes').textContent = document.getElementById('flavor-notes').value.trim() || '\u2014'; var depositAmount = flavorCalculateDeposit(); var depositBox = document.getElementById('flavorDepositBox'); var cardBox = document.getElementById('flavorCardInputBox'); if (depositAmount > 0 && flavorStripeKey) { depositBox.style.display = 'block'; cardBox.style.display = 'block'; document.getElementById('flavorDepAmount').textContent = depositAmount.toFixed(2) + ' \u20AC'; var perPerson = flavorDepositPerPerson > 0 ? (flavorData.guests + ' \u00D7 ' + flavorDepositPerPerson.toFixed(2) + ' \u20AC ' + flavorI18n.perPerson) : ''; document.getElementById('flavorDepSub').textContent = perPerson; document.getElementById('flavor-submit-text').style.display = 'none'; document.getElementById('flavor-submit-text-pay').style.display = 'inline'; } else { depositBox.style.display = 'none'; cardBox.style.display = 'none'; document.getElementById('flavor-submit-text').style.display = 'inline'; document.getElementById('flavor-submit-text-pay').style.display = 'none'; } } // ===================== // NAVIGATION BUTTONS // ===================== document.getElementById('flavorBtn1Next').addEventListener('click', function() { if (!flavorData.guests) { flavorToast(flavorI18n.selectGuests); return; } if (!flavorData.date) { flavorToast(flavorI18n.selectDate); return; } if (!flavorData.time) { flavorToast(flavorI18n.selectTime); return; } if (flavorTotalSteps === 2 && !flavorValidateStep2()) return; flavorGoStep(2); }); var btn2Back = document.getElementById('flavorBtn2Back'); if (btn2Back) btn2Back.addEventListener('click', function() { flavorGoStep(1); }); var btn2Next = document.getElementById('flavorBtn2Next'); if (btn2Next) btn2Next.addEventListener('click', function() { if (!flavorValidateStep2()) return; flavorGoStep(3); }); document.getElementById('flavorBtn3Back').addEventListener('click', function() { flavorGoStep(flavorTotalSteps === 2 ? 1 : 2); }); document.getElementById('flavorBtn3Confirm').addEventListener('click', function() { flavorSubmit(); }); // Stepper click document.querySelectorAll('.flavor-step-ind').forEach(function(el) { el.addEventListener('click', function() { var target = parseInt(el.dataset.step); if (target < flavorStep) flavorGoStep(target); }); }); // ===================== // DEPOSIT & STRIPE // ===================== function flavorCalculateDeposit() { if (!flavorRequireDeposit) return 0; return flavorDepositPerReservation + (flavorDepositPerPerson * (flavorData.guests || 0)); } function flavorInitStripe() { var depositAmount = flavorCalculateDeposit(); if (depositAmount > 0 && flavorStripeKey && !flavorStripe) { flavorStripe = Stripe(flavorStripeKey); var elements = flavorStripe.elements({locale: 'es'}); flavorCardElement = elements.create('card', { style: { base: { fontSize: '14px', color: '#1a1a1a', fontFamily: 'Inter, -apple-system, sans-serif', '::placeholder': { color: '#c0c0c0' } }, invalid: { color: '#dc2626' } } }); flavorCardElement.mount('#flavor-card-element'); flavorCardElement.on('change', function(event) { document.getElementById('flavor-card-errors').textContent = event.error ? event.error.message : ''; }); } } // ===================== // SUBMIT // ===================== function flavorSubmit() { var _chk = document.getElementById('flavor-accept-terms'); if (_chk && !_chk.checked) { flavorToast(flavorI18n.acceptTerms); return; } // In 2-step mode, validate step2 fields before submit if (flavorTotalSteps === 2 && !flavorValidateStep2()) return; var depositAmount = flavorCalculateDeposit(); if (depositAmount > 0 && flavorStripeKey && flavorCardElement) { flavorSubmitWithPayment(); } else { flavorSubmitWithoutPayment(); } } function flavorGetPostData() { var prefix = document.getElementById('flavor-prefix').value; var phone = document.getElementById('flavor-phone').value.trim(); return { restaurant_id: flavorRestaurantId, shortcode_key: flavorShortcodeKey, guests: flavorData.guests, reservation_date: flavorData.date, reservation_time: flavorData.time, first_name: document.getElementById('flavor-first-name').value, last_name: document.getElementById('flavor-last-name').value, email: document.getElementById('flavor-email').value, phone: prefix + phone, allergies: document.getElementById('flavor-allergies').value, dietary_restrictions: '', notes: document.getElementById('flavor-notes').value, shared_table: flavorData.shared ? 1 : 0 }; } function flavorSubmitWithoutPayment() { document.querySelector('.flavor-loader').style.display = 'flex'; fetch(flavorRestUrl + 'reservations', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(flavorGetPostData()) }) .then(function(r) { return r.json(); }) .then(function(r) { document.querySelector('.flavor-loader').style.display = 'none'; if (r.success) { flavorShowSuccess(r.reservation.reservation || r.reservation); } else { flavorShowError(r.message || 'Error al crear la reserva'); } }) .catch(function() { document.querySelector('.flavor-loader').style.display = 'none'; flavorShowError(flavorI18n.error); }); } function flavorSubmitWithPayment() { var submitBtn = document.getElementById('flavorBtn3Confirm'); submitBtn.disabled = true; submitBtn.innerHTML = '' + flavorI18n.paymentProcessing + ''; var postData = flavorGetPostData(); var customerName = postData.first_name + ' ' + postData.last_name; var customerEmail = postData.email; fetch(flavorRestUrl + 'payment/create-intent', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ restaurant_id: flavorRestaurantId, guests: flavorData.guests, name: customerName, email: customerEmail }) }) .then(function(resp) { return resp.json(); }) .then(function(paymentData) { if (!paymentData.success) throw new Error(paymentData.message || 'Error al iniciar el pago'); return flavorStripe.confirmCardPayment(paymentData.data.client_secret, { payment_method: { card: flavorCardElement, billing_details: { name: customerName, email: customerEmail } } }).then(function(result) { if (result.error) throw new Error(result.error.message); return result.paymentIntent.id; }); }) .then(function(paymentIntentId) { postData.payment_intent_id = paymentIntentId; postData.deposit_paid = 1; return fetch(flavorRestUrl + 'reservations', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(postData) }); }) .then(function(response) { return response.json(); }) .then(function(r) { if (!r.success) throw new Error(r.message || 'Error al crear la reserva'); submitBtn.disabled = false; flavorShowSuccess(r.reservation.reservation || r.reservation); }) .catch(function(error) { submitBtn.disabled = false; submitBtn.innerHTML = '' + flavorI18n.paymentProcessing + ''; document.getElementById('flavor-card-errors').textContent = error.message; flavorToast(error.message); }); } // ===================== // SUCCESS / ERROR // ===================== // Ejecuta un snippet de tracking pegado por el restaurante desde el backoffice. // El snippet se sirve como
1
Book your table
2
Pay and confirm
Book your table
Guests
Date
Time

Select a date to see available times

Your details
I prefer shared table
Confirm your reservation
Guests
—
Date
—
Time
—
First name
—
Email
—
Phone
—
Shared table
—
Notes
—
A deposit is required to confirm your reservation
0.00 €
Reembolsable si cancelas con 24h de antelación
Card details
I accept the booking conditions and the privacy policy
Condiciones de reserva

Reserva y puntualidad
Mantendremos tu mesa reservada durante 15 minutos de cortesía. Si prevés llegar más tarde, te agradeceremos que nos lo comuniques. En caso contrario, no podremos garantizar la disponibilidad de la reserva.

Cancelaciones
Las cancelaciones realizadas con menos de 24 horas de antelación no serán reembolsables en ningún caso.

Edad mínima
El acceso está permitido únicamente a mayores de 14 años.

Mascotas
Las mascotas son bienvenidas en nuestra terraza, siempre que permanezcan limpias, tranquilas, atadas y bajo la supervisión de su responsable, evitando en todo momento molestias al resto de los clientes. Nos reservamos el derecho de asignar la mesa que consideremos más adecuada. Durante la temporada de invierno, te rogamos que nos consultes antes de realizar la reserva.

Código de vestimenta
Agradecemos una vestimenta smart casual: elegante, cómoda e informal.

Convivencia
Te rogamos mantener un ambiente tranquilo, evitando alzar la voz y mostrando respeto tanto hacia los demás clientes como hacia nuestro equipo. Está permitido fumar únicamente en la zona habilitada para ello.

Restricciones alimentarias
Si tienes alguna alergia, intolerancia o restricción alimentaria, te agradeceremos que nos lo comuniques antes de tu llegada. Una vez iniciado el servicio, no podemos garantizar que sea posible realizar modificaciones en el menú.

Con el fin de preservar el ambiente y el bienestar de todos los presentes, nos reservamos el derecho de solicitar el abandono del establecimiento en caso de comportamientos que alteren la convivencia o el normal desarrollo del servicio.

Processing...

Manage reservation

← Back to booking
📅
🕐
👥
👤
✉️
📞
⚠️
🥗
📝

🍽️ Menu selection

Starters
Main courses
Desserts

Modify reservation

🍽️ Menu selection

'; }).join(''); var offset = (new Date(flavorCalYear, flavorCalMonth, 1).getDay() + 6) % 7; var dim = new Date(flavorCalYear, flavorCalMonth + 1, 0).getDate(); for (var i = 0; i < offset; i++) h += '
'; var minStr = formatDateLocal(flavorMinDate); var maxStr = formatDateLocal(flavorMaxDate); for (var d = 1; d <= dim; d++) { var date = new Date(flavorCalYear, flavorCalMonth, d); var dateStr = formatDateLocal(date); var isSel = flavorData.date === dateStr; var isToday = date.toDateString() === today.toDateString(); var isPast = dateStr < minStr || dateStr > maxStr; var isClosed = !isPast && flavorOpenDays.indexOf(date.getDay()) === -1; var isBlocked = !isPast && !isClosed && flavorBlockedDates[dateStr]; var cls = 'flavor-cal-day'; if (isPast) cls += ' past'; else if (isClosed || isBlocked) cls += ' closed'; else if (isSel) cls += ' on'; else if (isToday) cls += ' today'; if (isPast || isClosed || isBlocked) { h += '
' + d + '
'; } else { h += ''; } } grid.innerHTML = h; grid.querySelectorAll('.flavor-cal-day[data-date]').forEach(function(b) { b.addEventListener('click', function() { flavorData.date = b.dataset.date; flavorData.time = null; flavorRenderCalendar(); flavorLoadTimeSlots(flavorData.date); }); }); } document.getElementById('flavorCalPrev').addEventListener('click', function() { var now = new Date(); if (flavorCalMonth <= now.getMonth() && flavorCalYear <= now.getFullYear()) return; flavorCalMonth--; if (flavorCalMonth < 0) { flavorCalMonth = 11; flavorCalYear--; } flavorRenderCalendar(); }); document.getElementById('flavorCalNext').addEventListener('click', function() { flavorCalMonth++; if (flavorCalMonth > 11) { flavorCalMonth = 0; flavorCalYear++; } flavorRenderCalendar(); }); // ===================== // TIME SLOTS // ===================== function flavorLoadTimeSlots(dateStr) { var container = document.getElementById('flavorSlots'); var guests = flavorData.guests || 2; container.innerHTML = '

' + flavorI18n.loadingTimes + '

'; fetch(flavorRestUrl + 'restaurants/' + flavorRestaurantId + '/available-slots?date=' + dateStr + '&guests=' + guests) .then(function(r) { return r.json(); }) .then(function(data) { if (data.success && data.data && data.data.length > 0) { var html = ''; data.data.forEach(function(slot) { var timeShort = slot.time.substring(0, 5); if (slot.available) { var cls = 'flavor-slot' + (flavorData.time === timeShort ? ' on' : ''); html += ''; } else { var reasonText = flavorI18n.notAvailable; if (slot.reason === 'capacity') reasonText = flavorI18n.capacityFull; else if (slot.reason === 'max_reservations') reasonText = flavorI18n.maxReservations; else if (slot.reason === 'min_advance') reasonText = flavorI18n.minAdvance; html += ''; } }); container.innerHTML = html; container.querySelectorAll('.flavor-slot:not(.busy)').forEach(function(b) { b.addEventListener('click', function() { flavorData.time = b.dataset.t; container.querySelectorAll('.flavor-slot').forEach(function(s) { s.classList.remove('on'); }); b.classList.add('on'); flavorCheckStep1(); }); }); } else { container.innerHTML = '

' + flavorI18n.noTimesAvailable + '

'; } }) .catch(function() { container.innerHTML = '

' + flavorI18n.errorLoadingTimes + '

'; }); } // ===================== // CHIPS (Guests) // ===================== document.getElementById('flavorChips').addEventListener('click', function(e) { var c = e.target.closest('.flavor-chip'); if (!c) return; flavorData.guests = parseInt(c.dataset.val); document.querySelectorAll('.flavor-chip').forEach(function(x) { x.classList.remove('on'); }); c.classList.add('on'); if (flavorData.date) { flavorData.time = null; flavorLoadTimeSlots(flavorData.date); } flavorCheckStep1(); }); // ===================== // SHARED TABLE TOGGLE // ===================== var sharedToggle = document.getElementById('flavorSharedToggle'); if (sharedToggle) { sharedToggle.addEventListener('click', function() { flavorData.shared = !flavorData.shared; sharedToggle.classList.toggle('on', flavorData.shared); }); } // ===================== // VALIDATIONS // ===================== function flavorCheckStep1() { var hasBooking = !!(flavorData.date && flavorData.time); if (flavorTotalSteps === 2) { // In 2-step mode, step 1 also contains data fields var hasData = ['flavor-first-name','flavor-last-name','flavor-email','flavor-phone'].every(function(id) { return document.getElementById(id).value.trim() !== ''; }); document.getElementById('flavorBtn1Next').disabled = !(hasBooking && hasData); } else { document.getElementById('flavorBtn1Next').disabled = !hasBooking; } } function flavorCheckStep2() { var ok = ['flavor-first-name','flavor-last-name','flavor-email','flavor-phone'].every(function(id) { return document.getElementById(id).value.trim() !== ''; }); var btn2 = document.getElementById('flavorBtn2Next'); if (btn2) btn2.disabled = !ok; } function flavorCheckStep3() { var chk = document.getElementById('flavor-accept-terms'); // El checkbox solo existe si procede; si no está, el botón queda disponible document.getElementById('flavorBtn3Confirm').disabled = chk ? !chk.checked : false; } ['flavor-first-name','flavor-last-name','flavor-email','flavor-phone'].forEach(function(id) { document.getElementById(id).addEventListener('input', function() { flavorCheckStep2(); if (flavorTotalSteps === 2) flavorCheckStep1(); }); }); (function(){ var chk = document.getElementById('flavor-accept-terms'); if (chk) chk.addEventListener('change', flavorCheckStep3); })(); function flavorValidateStep2() { var fn = document.getElementById('flavor-first-name').value.trim(); var ln = document.getElementById('flavor-last-name').value.trim(); var em = document.getElementById('flavor-email').value.trim(); var ph = document.getElementById('flavor-phone').value.trim(); if (!fn) { flavorToast(flavorI18n.nameRequired); return false; } if (!ln) { flavorToast(flavorI18n.lastNameRequired); return false; } if (!em) { flavorToast(flavorI18n.emailRequired); return false; } if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(em)) { flavorToast(flavorI18n.emailInvalid); return false; } if (!ph) { flavorToast(flavorI18n.phoneRequired); return false; } return true; } // ===================== // SUMMARY // ===================== function flavorBuildSummary() { document.getElementById('sumGuests').textContent = flavorData.guests + ' ' + (flavorData.guests === 1 ? flavorI18n.person : flavorI18n.people); if (flavorData.date) { var parts = flavorData.date.split('-'); var d = new Date(parseInt(parts[0]), parseInt(parts[1]) - 1, parseInt(parts[2])); var dn = flavorI18n.dayNames[d.getDay()].toLowerCase(); document.getElementById('sumDate').textContent = dn + ', ' + parseInt(parts[2]) + ' de ' + flavorI18n.months[parseInt(parts[1]) - 1].toLowerCase() + ' ' + parts[0]; } document.getElementById('sumTime').textContent = flavorData.time ? flavorData.time + 'h' : '\u2014'; var fn = document.getElementById('flavor-first-name').value.trim(); var ln = document.getElementById('flavor-last-name').value.trim(); document.getElementById('sumName').textContent = (fn + ' ' + ln).trim() || '\u2014'; document.getElementById('sumEmail').textContent = document.getElementById('flavor-email').value.trim() || '\u2014'; var pre = document.getElementById('flavor-prefix').value; var ph = document.getElementById('flavor-phone').value.trim(); document.getElementById('sumPhone').textContent = ph ? pre + ph : '\u2014'; document.getElementById('sumShared').textContent = flavorData.shared ? flavorI18n.yes : flavorI18n.no; document.getElementById('sumNotes').textContent = document.getElementById('flavor-notes').value.trim() || '\u2014'; var depositAmount = flavorCalculateDeposit(); var depositBox = document.getElementById('flavorDepositBox'); var cardBox = document.getElementById('flavorCardInputBox'); if (depositAmount > 0 && flavorStripeKey) { depositBox.style.display = 'block'; cardBox.style.display = 'block'; document.getElementById('flavorDepAmount').textContent = depositAmount.toFixed(2) + ' \u20AC'; var perPerson = flavorDepositPerPerson > 0 ? (flavorData.guests + ' \u00D7 ' + flavorDepositPerPerson.toFixed(2) + ' \u20AC ' + flavorI18n.perPerson) : ''; document.getElementById('flavorDepSub').textContent = perPerson; document.getElementById('flavor-submit-text').style.display = 'none'; document.getElementById('flavor-submit-text-pay').style.display = 'inline'; } else { depositBox.style.display = 'none'; cardBox.style.display = 'none'; document.getElementById('flavor-submit-text').style.display = 'inline'; document.getElementById('flavor-submit-text-pay').style.display = 'none'; } } // ===================== // NAVIGATION BUTTONS // ===================== document.getElementById('flavorBtn1Next').addEventListener('click', function() { if (!flavorData.guests) { flavorToast(flavorI18n.selectGuests); return; } if (!flavorData.date) { flavorToast(flavorI18n.selectDate); return; } if (!flavorData.time) { flavorToast(flavorI18n.selectTime); return; } if (flavorTotalSteps === 2 && !flavorValidateStep2()) return; flavorGoStep(2); }); var btn2Back = document.getElementById('flavorBtn2Back'); if (btn2Back) btn2Back.addEventListener('click', function() { flavorGoStep(1); }); var btn2Next = document.getElementById('flavorBtn2Next'); if (btn2Next) btn2Next.addEventListener('click', function() { if (!flavorValidateStep2()) return; flavorGoStep(3); }); document.getElementById('flavorBtn3Back').addEventListener('click', function() { flavorGoStep(flavorTotalSteps === 2 ? 1 : 2); }); document.getElementById('flavorBtn3Confirm').addEventListener('click', function() { flavorSubmit(); }); // Stepper click document.querySelectorAll('.flavor-step-ind').forEach(function(el) { el.addEventListener('click', function() { var target = parseInt(el.dataset.step); if (target < flavorStep) flavorGoStep(target); }); }); // ===================== // DEPOSIT & STRIPE // ===================== function flavorCalculateDeposit() { if (!flavorRequireDeposit) return 0; return flavorDepositPerReservation + (flavorDepositPerPerson * (flavorData.guests || 0)); } function flavorInitStripe() { var depositAmount = flavorCalculateDeposit(); if (depositAmount > 0 && flavorStripeKey && !flavorStripe) { flavorStripe = Stripe(flavorStripeKey); var elements = flavorStripe.elements({locale: 'es'}); flavorCardElement = elements.create('card', { style: { base: { fontSize: '14px', color: '#1a1a1a', fontFamily: 'Inter, -apple-system, sans-serif', '::placeholder': { color: '#c0c0c0' } }, invalid: { color: '#dc2626' } } }); flavorCardElement.mount('#flavor-card-element'); flavorCardElement.on('change', function(event) { document.getElementById('flavor-card-errors').textContent = event.error ? event.error.message : ''; }); } } // ===================== // SUBMIT // ===================== function flavorSubmit() { var _chk = document.getElementById('flavor-accept-terms'); if (_chk && !_chk.checked) { flavorToast(flavorI18n.acceptTerms); return; } // In 2-step mode, validate step2 fields before submit if (flavorTotalSteps === 2 && !flavorValidateStep2()) return; var depositAmount = flavorCalculateDeposit(); if (depositAmount > 0 && flavorStripeKey && flavorCardElement) { flavorSubmitWithPayment(); } else { flavorSubmitWithoutPayment(); } } function flavorGetPostData() { var prefix = document.getElementById('flavor-prefix').value; var phone = document.getElementById('flavor-phone').value.trim(); return { restaurant_id: flavorRestaurantId, shortcode_key: flavorShortcodeKey, guests: flavorData.guests, reservation_date: flavorData.date, reservation_time: flavorData.time, first_name: document.getElementById('flavor-first-name').value, last_name: document.getElementById('flavor-last-name').value, email: document.getElementById('flavor-email').value, phone: prefix + phone, allergies: document.getElementById('flavor-allergies').value, dietary_restrictions: '', notes: document.getElementById('flavor-notes').value, shared_table: flavorData.shared ? 1 : 0 }; } function flavorSubmitWithoutPayment() { document.querySelector('.flavor-loader').style.display = 'flex'; fetch(flavorRestUrl + 'reservations', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(flavorGetPostData()) }) .then(function(r) { return r.json(); }) .then(function(r) { document.querySelector('.flavor-loader').style.display = 'none'; if (r.success) { flavorShowSuccess(r.reservation.reservation || r.reservation); } else { flavorShowError(r.message || 'Error al crear la reserva'); } }) .catch(function() { document.querySelector('.flavor-loader').style.display = 'none'; flavorShowError(flavorI18n.error); }); } function flavorSubmitWithPayment() { var submitBtn = document.getElementById('flavorBtn3Confirm'); submitBtn.disabled = true; submitBtn.innerHTML = '' + flavorI18n.paymentProcessing + ''; var postData = flavorGetPostData(); var customerName = postData.first_name + ' ' + postData.last_name; var customerEmail = postData.email; fetch(flavorRestUrl + 'payment/create-intent', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ restaurant_id: flavorRestaurantId, guests: flavorData.guests, name: customerName, email: customerEmail }) }) .then(function(resp) { return resp.json(); }) .then(function(paymentData) { if (!paymentData.success) throw new Error(paymentData.message || 'Error al iniciar el pago'); return flavorStripe.confirmCardPayment(paymentData.data.client_secret, { payment_method: { card: flavorCardElement, billing_details: { name: customerName, email: customerEmail } } }).then(function(result) { if (result.error) throw new Error(result.error.message); return result.paymentIntent.id; }); }) .then(function(paymentIntentId) { postData.payment_intent_id = paymentIntentId; postData.deposit_paid = 1; return fetch(flavorRestUrl + 'reservations', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(postData) }); }) .then(function(response) { return response.json(); }) .then(function(r) { if (!r.success) throw new Error(r.message || 'Error al crear la reserva'); submitBtn.disabled = false; flavorShowSuccess(r.reservation.reservation || r.reservation); }) .catch(function(error) { submitBtn.disabled = false; submitBtn.innerHTML = '' + flavorI18n.paymentProcessing + ''; document.getElementById('flavor-card-errors').textContent = error.message; flavorToast(error.message); }); } // ===================== // SUCCESS / ERROR // ===================== // Ejecuta un snippet de tracking pegado por el restaurante desde el backoffice. // El snippet se sirve como
1
Tisch reservieren
2
Bezahlen und bestätigen
Tisch reservieren
Gäste
Datum
Zeit

Wählen Sie ein Datum, um verfügbare Zeiten zu sehen

Ihre Daten
Ich wünsche geteilten Tisch
Reservierung bestätigen
Gäste
—
Datum
—
Zeit
—
Vorname
—
E-Mail
—
Telefon
—
Geteilter Tisch
—
Bemerkungen
—
Eine Anzahlung ist erforderlich, um Ihre Reservierung zu bestätigen
0.00 €
Reembolsable si cancelas con 24h de antelación
Kartendaten
Ich akzeptiere die Reservierungsbedingungen und die Datenschutzrichtlinie
Condiciones de reserva

Reserva y puntualidad
Mantendremos tu mesa reservada durante 15 minutos de cortesía. Si prevés llegar más tarde, te agradeceremos que nos lo comuniques. En caso contrario, no podremos garantizar la disponibilidad de la reserva.

Cancelaciones
Las cancelaciones realizadas con menos de 24 horas de antelación no serán reembolsables en ningún caso.

Edad mínima
El acceso está permitido únicamente a mayores de 14 años.

Mascotas
Las mascotas son bienvenidas en nuestra terraza, siempre que permanezcan limpias, tranquilas, atadas y bajo la supervisión de su responsable, evitando en todo momento molestias al resto de los clientes. Nos reservamos el derecho de asignar la mesa que consideremos más adecuada. Durante la temporada de invierno, te rogamos que nos consultes antes de realizar la reserva.

Código de vestimenta
Agradecemos una vestimenta smart casual: elegante, cómoda e informal.

Convivencia
Te rogamos mantener un ambiente tranquilo, evitando alzar la voz y mostrando respeto tanto hacia los demás clientes como hacia nuestro equipo. Está permitido fumar únicamente en la zona habilitada para ello.

Restricciones alimentarias
Si tienes alguna alergia, intolerancia o restricción alimentaria, te agradeceremos que nos lo comuniques antes de tu llegada. Una vez iniciado el servicio, no podemos garantizar que sea posible realizar modificaciones en el menú.

Con el fin de preservar el ambiente y el bienestar de todos los presentes, nos reservamos el derecho de solicitar el abandono del establecimiento en caso de comportamientos que alteren la convivencia o el normal desarrollo del servicio.

Wird verarbeitet...

Reservierung verwalten

← Zurück zur Buchung
📅
🕐
👥
👤
✉️
📞
⚠️
🥗
📝

🍽️ Menüauswahl

Vorspeisen
Hauptgerichte
Desserts

Reservierung ändern

🍽️ Menüauswahl

'; }).join(''); var offset = (new Date(flavorCalYear, flavorCalMonth, 1).getDay() + 6) % 7; var dim = new Date(flavorCalYear, flavorCalMonth + 1, 0).getDate(); for (var i = 0; i < offset; i++) h += '
'; var minStr = formatDateLocal(flavorMinDate); var maxStr = formatDateLocal(flavorMaxDate); for (var d = 1; d <= dim; d++) { var date = new Date(flavorCalYear, flavorCalMonth, d); var dateStr = formatDateLocal(date); var isSel = flavorData.date === dateStr; var isToday = date.toDateString() === today.toDateString(); var isPast = dateStr < minStr || dateStr > maxStr; var isClosed = !isPast && flavorOpenDays.indexOf(date.getDay()) === -1; var isBlocked = !isPast && !isClosed && flavorBlockedDates[dateStr]; var cls = 'flavor-cal-day'; if (isPast) cls += ' past'; else if (isClosed || isBlocked) cls += ' closed'; else if (isSel) cls += ' on'; else if (isToday) cls += ' today'; if (isPast || isClosed || isBlocked) { h += '
' + d + '
'; } else { h += ''; } } grid.innerHTML = h; grid.querySelectorAll('.flavor-cal-day[data-date]').forEach(function(b) { b.addEventListener('click', function() { flavorData.date = b.dataset.date; flavorData.time = null; flavorRenderCalendar(); flavorLoadTimeSlots(flavorData.date); }); }); } document.getElementById('flavorCalPrev').addEventListener('click', function() { var now = new Date(); if (flavorCalMonth <= now.getMonth() && flavorCalYear <= now.getFullYear()) return; flavorCalMonth--; if (flavorCalMonth < 0) { flavorCalMonth = 11; flavorCalYear--; } flavorRenderCalendar(); }); document.getElementById('flavorCalNext').addEventListener('click', function() { flavorCalMonth++; if (flavorCalMonth > 11) { flavorCalMonth = 0; flavorCalYear++; } flavorRenderCalendar(); }); // ===================== // TIME SLOTS // ===================== function flavorLoadTimeSlots(dateStr) { var container = document.getElementById('flavorSlots'); var guests = flavorData.guests || 2; container.innerHTML = '

' + flavorI18n.loadingTimes + '

'; fetch(flavorRestUrl + 'restaurants/' + flavorRestaurantId + '/available-slots?date=' + dateStr + '&guests=' + guests) .then(function(r) { return r.json(); }) .then(function(data) { if (data.success && data.data && data.data.length > 0) { var html = ''; data.data.forEach(function(slot) { var timeShort = slot.time.substring(0, 5); if (slot.available) { var cls = 'flavor-slot' + (flavorData.time === timeShort ? ' on' : ''); html += ''; } else { var reasonText = flavorI18n.notAvailable; if (slot.reason === 'capacity') reasonText = flavorI18n.capacityFull; else if (slot.reason === 'max_reservations') reasonText = flavorI18n.maxReservations; else if (slot.reason === 'min_advance') reasonText = flavorI18n.minAdvance; html += ''; } }); container.innerHTML = html; container.querySelectorAll('.flavor-slot:not(.busy)').forEach(function(b) { b.addEventListener('click', function() { flavorData.time = b.dataset.t; container.querySelectorAll('.flavor-slot').forEach(function(s) { s.classList.remove('on'); }); b.classList.add('on'); flavorCheckStep1(); }); }); } else { container.innerHTML = '

' + flavorI18n.noTimesAvailable + '

'; } }) .catch(function() { container.innerHTML = '

' + flavorI18n.errorLoadingTimes + '

'; }); } // ===================== // CHIPS (Guests) // ===================== document.getElementById('flavorChips').addEventListener('click', function(e) { var c = e.target.closest('.flavor-chip'); if (!c) return; flavorData.guests = parseInt(c.dataset.val); document.querySelectorAll('.flavor-chip').forEach(function(x) { x.classList.remove('on'); }); c.classList.add('on'); if (flavorData.date) { flavorData.time = null; flavorLoadTimeSlots(flavorData.date); } flavorCheckStep1(); }); // ===================== // SHARED TABLE TOGGLE // ===================== var sharedToggle = document.getElementById('flavorSharedToggle'); if (sharedToggle) { sharedToggle.addEventListener('click', function() { flavorData.shared = !flavorData.shared; sharedToggle.classList.toggle('on', flavorData.shared); }); } // ===================== // VALIDATIONS // ===================== function flavorCheckStep1() { var hasBooking = !!(flavorData.date && flavorData.time); if (flavorTotalSteps === 2) { // In 2-step mode, step 1 also contains data fields var hasData = ['flavor-first-name','flavor-last-name','flavor-email','flavor-phone'].every(function(id) { return document.getElementById(id).value.trim() !== ''; }); document.getElementById('flavorBtn1Next').disabled = !(hasBooking && hasData); } else { document.getElementById('flavorBtn1Next').disabled = !hasBooking; } } function flavorCheckStep2() { var ok = ['flavor-first-name','flavor-last-name','flavor-email','flavor-phone'].every(function(id) { return document.getElementById(id).value.trim() !== ''; }); var btn2 = document.getElementById('flavorBtn2Next'); if (btn2) btn2.disabled = !ok; } function flavorCheckStep3() { var chk = document.getElementById('flavor-accept-terms'); // El checkbox solo existe si procede; si no está, el botón queda disponible document.getElementById('flavorBtn3Confirm').disabled = chk ? !chk.checked : false; } ['flavor-first-name','flavor-last-name','flavor-email','flavor-phone'].forEach(function(id) { document.getElementById(id).addEventListener('input', function() { flavorCheckStep2(); if (flavorTotalSteps === 2) flavorCheckStep1(); }); }); (function(){ var chk = document.getElementById('flavor-accept-terms'); if (chk) chk.addEventListener('change', flavorCheckStep3); })(); function flavorValidateStep2() { var fn = document.getElementById('flavor-first-name').value.trim(); var ln = document.getElementById('flavor-last-name').value.trim(); var em = document.getElementById('flavor-email').value.trim(); var ph = document.getElementById('flavor-phone').value.trim(); if (!fn) { flavorToast(flavorI18n.nameRequired); return false; } if (!ln) { flavorToast(flavorI18n.lastNameRequired); return false; } if (!em) { flavorToast(flavorI18n.emailRequired); return false; } if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(em)) { flavorToast(flavorI18n.emailInvalid); return false; } if (!ph) { flavorToast(flavorI18n.phoneRequired); return false; } return true; } // ===================== // SUMMARY // ===================== function flavorBuildSummary() { document.getElementById('sumGuests').textContent = flavorData.guests + ' ' + (flavorData.guests === 1 ? flavorI18n.person : flavorI18n.people); if (flavorData.date) { var parts = flavorData.date.split('-'); var d = new Date(parseInt(parts[0]), parseInt(parts[1]) - 1, parseInt(parts[2])); var dn = flavorI18n.dayNames[d.getDay()].toLowerCase(); document.getElementById('sumDate').textContent = dn + ', ' + parseInt(parts[2]) + ' de ' + flavorI18n.months[parseInt(parts[1]) - 1].toLowerCase() + ' ' + parts[0]; } document.getElementById('sumTime').textContent = flavorData.time ? flavorData.time + 'h' : '\u2014'; var fn = document.getElementById('flavor-first-name').value.trim(); var ln = document.getElementById('flavor-last-name').value.trim(); document.getElementById('sumName').textContent = (fn + ' ' + ln).trim() || '\u2014'; document.getElementById('sumEmail').textContent = document.getElementById('flavor-email').value.trim() || '\u2014'; var pre = document.getElementById('flavor-prefix').value; var ph = document.getElementById('flavor-phone').value.trim(); document.getElementById('sumPhone').textContent = ph ? pre + ph : '\u2014'; document.getElementById('sumShared').textContent = flavorData.shared ? flavorI18n.yes : flavorI18n.no; document.getElementById('sumNotes').textContent = document.getElementById('flavor-notes').value.trim() || '\u2014'; var depositAmount = flavorCalculateDeposit(); var depositBox = document.getElementById('flavorDepositBox'); var cardBox = document.getElementById('flavorCardInputBox'); if (depositAmount > 0 && flavorStripeKey) { depositBox.style.display = 'block'; cardBox.style.display = 'block'; document.getElementById('flavorDepAmount').textContent = depositAmount.toFixed(2) + ' \u20AC'; var perPerson = flavorDepositPerPerson > 0 ? (flavorData.guests + ' \u00D7 ' + flavorDepositPerPerson.toFixed(2) + ' \u20AC ' + flavorI18n.perPerson) : ''; document.getElementById('flavorDepSub').textContent = perPerson; document.getElementById('flavor-submit-text').style.display = 'none'; document.getElementById('flavor-submit-text-pay').style.display = 'inline'; } else { depositBox.style.display = 'none'; cardBox.style.display = 'none'; document.getElementById('flavor-submit-text').style.display = 'inline'; document.getElementById('flavor-submit-text-pay').style.display = 'none'; } } // ===================== // NAVIGATION BUTTONS // ===================== document.getElementById('flavorBtn1Next').addEventListener('click', function() { if (!flavorData.guests) { flavorToast(flavorI18n.selectGuests); return; } if (!flavorData.date) { flavorToast(flavorI18n.selectDate); return; } if (!flavorData.time) { flavorToast(flavorI18n.selectTime); return; } if (flavorTotalSteps === 2 && !flavorValidateStep2()) return; flavorGoStep(2); }); var btn2Back = document.getElementById('flavorBtn2Back'); if (btn2Back) btn2Back.addEventListener('click', function() { flavorGoStep(1); }); var btn2Next = document.getElementById('flavorBtn2Next'); if (btn2Next) btn2Next.addEventListener('click', function() { if (!flavorValidateStep2()) return; flavorGoStep(3); }); document.getElementById('flavorBtn3Back').addEventListener('click', function() { flavorGoStep(flavorTotalSteps === 2 ? 1 : 2); }); document.getElementById('flavorBtn3Confirm').addEventListener('click', function() { flavorSubmit(); }); // Stepper click document.querySelectorAll('.flavor-step-ind').forEach(function(el) { el.addEventListener('click', function() { var target = parseInt(el.dataset.step); if (target < flavorStep) flavorGoStep(target); }); }); // ===================== // DEPOSIT & STRIPE // ===================== function flavorCalculateDeposit() { if (!flavorRequireDeposit) return 0; return flavorDepositPerReservation + (flavorDepositPerPerson * (flavorData.guests || 0)); } function flavorInitStripe() { var depositAmount = flavorCalculateDeposit(); if (depositAmount > 0 && flavorStripeKey && !flavorStripe) { flavorStripe = Stripe(flavorStripeKey); var elements = flavorStripe.elements({locale: 'es'}); flavorCardElement = elements.create('card', { style: { base: { fontSize: '14px', color: '#1a1a1a', fontFamily: 'Inter, -apple-system, sans-serif', '::placeholder': { color: '#c0c0c0' } }, invalid: { color: '#dc2626' } } }); flavorCardElement.mount('#flavor-card-element'); flavorCardElement.on('change', function(event) { document.getElementById('flavor-card-errors').textContent = event.error ? event.error.message : ''; }); } } // ===================== // SUBMIT // ===================== function flavorSubmit() { var _chk = document.getElementById('flavor-accept-terms'); if (_chk && !_chk.checked) { flavorToast(flavorI18n.acceptTerms); return; } // In 2-step mode, validate step2 fields before submit if (flavorTotalSteps === 2 && !flavorValidateStep2()) return; var depositAmount = flavorCalculateDeposit(); if (depositAmount > 0 && flavorStripeKey && flavorCardElement) { flavorSubmitWithPayment(); } else { flavorSubmitWithoutPayment(); } } function flavorGetPostData() { var prefix = document.getElementById('flavor-prefix').value; var phone = document.getElementById('flavor-phone').value.trim(); return { restaurant_id: flavorRestaurantId, shortcode_key: flavorShortcodeKey, guests: flavorData.guests, reservation_date: flavorData.date, reservation_time: flavorData.time, first_name: document.getElementById('flavor-first-name').value, last_name: document.getElementById('flavor-last-name').value, email: document.getElementById('flavor-email').value, phone: prefix + phone, allergies: document.getElementById('flavor-allergies').value, dietary_restrictions: '', notes: document.getElementById('flavor-notes').value, shared_table: flavorData.shared ? 1 : 0 }; } function flavorSubmitWithoutPayment() { document.querySelector('.flavor-loader').style.display = 'flex'; fetch(flavorRestUrl + 'reservations', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(flavorGetPostData()) }) .then(function(r) { return r.json(); }) .then(function(r) { document.querySelector('.flavor-loader').style.display = 'none'; if (r.success) { flavorShowSuccess(r.reservation.reservation || r.reservation); } else { flavorShowError(r.message || 'Error al crear la reserva'); } }) .catch(function() { document.querySelector('.flavor-loader').style.display = 'none'; flavorShowError(flavorI18n.error); }); } function flavorSubmitWithPayment() { var submitBtn = document.getElementById('flavorBtn3Confirm'); submitBtn.disabled = true; submitBtn.innerHTML = '' + flavorI18n.paymentProcessing + ''; var postData = flavorGetPostData(); var customerName = postData.first_name + ' ' + postData.last_name; var customerEmail = postData.email; fetch(flavorRestUrl + 'payment/create-intent', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ restaurant_id: flavorRestaurantId, guests: flavorData.guests, name: customerName, email: customerEmail }) }) .then(function(resp) { return resp.json(); }) .then(function(paymentData) { if (!paymentData.success) throw new Error(paymentData.message || 'Error al iniciar el pago'); return flavorStripe.confirmCardPayment(paymentData.data.client_secret, { payment_method: { card: flavorCardElement, billing_details: { name: customerName, email: customerEmail } } }).then(function(result) { if (result.error) throw new Error(result.error.message); return result.paymentIntent.id; }); }) .then(function(paymentIntentId) { postData.payment_intent_id = paymentIntentId; postData.deposit_paid = 1; return fetch(flavorRestUrl + 'reservations', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(postData) }); }) .then(function(response) { return response.json(); }) .then(function(r) { if (!r.success) throw new Error(r.message || 'Error al crear la reserva'); submitBtn.disabled = false; flavorShowSuccess(r.reservation.reservation || r.reservation); }) .catch(function(error) { submitBtn.disabled = false; submitBtn.innerHTML = '' + flavorI18n.paymentProcessing + ''; document.getElementById('flavor-card-errors').textContent = error.message; flavorToast(error.message); }); } // ===================== // SUCCESS / ERROR // ===================== // Ejecuta un snippet de tracking pegado por el restaurante desde el backoffice. // El snippet se sirve como
Miguel Miralles

Miquel Miralles, Treurer's CEO, is part of the owner family, being already the second generation involved in the project. He has a background in economics and law, and has taken numerous courses related to foreign trade, olive agronomy and extra virgin olive oil production techniques. His training and experience of more than 15 years in the world of olive oil are her guarantee to lead this project.

Entradas recientes

  • Blog
  • Unkategorisiert
  • Turismo

Pollença: Erbe, Kunst und Spiritualität im Herzen Mallorcas

Entdecke Pollença, Wiege der Kunst und Spiritualität auf Mallorca: Kirchen, der Kalvarienberg, künstlerische Tradition und…

3 Wochen hace
  • Blog
  • Blog
  • Gourmet
  • Gourmet

Wintergastronomie auf Mallorca: Saisongerichte und neues Olivenöl

Entdecke die Wintergastronomie auf Mallorca: Saisongerichte, traditionelle Rezepte und das neue Ernte-Olivenöl, das jeden Bissen…

4 Wochen hace
  • Unkategorisiert

Finca Raixa

Finca Raixa – ein ikonisches Anwesen am Fuße der Sierra de Tramuntana auf Mallorca mit…

3 Monaten hace
  • Unkategorisiert

Wesentlicher Leitfaden zum Flughafen Mallorca

Alles, was Sie über den Flughafen Mallorca wissen müssen: Lage, Anreise, Terminal, Services und praktische…

3 Monaten hace
  • Blog
  • Gourmet
  • Unkategorisiert

Traditionelle mallorquinische Küche: Holzofen, Ton und langsames Feuer

Holzofen, Tonschüssel und langsames Feuer: die drei Säulen der traditionellen mallorquinischen Küche. Geschichte, Techniken, Rezept…

3 Monaten hace
  • Blog

Alperujo als Dünger: das Kreislaufwirtschaftsmodell von Treurer

Finca Treurer auf Mallorca verwandelt Alperujo in Kompost, nutzt Wasser und Solarenergie wieder – ein…

3 Monaten hace