{% if app.request.get('product') =="appartement" %}
{% include checkCustomTemplate("SejourAppartement/availability/vuejs-components/item-hotel-content.html.twig") %}
{% else %}
{% include checkCustomTemplate("SejourHotel/availability/vuejs-components/item-hotel-content.html.twig") %}
{% endif %}
{{ macro('sejour-hotel.availability').jsComponentSupplement() }}
{% include checkCustomTemplate("SejourHotel/availability/vuejs-components/item-pension-room/#{resultView}.html.twig") %}
<script>
let allHotels = {{ getAllHotels(null, false, app.request.get('product') == "appartement")|json_encode|raw }};
var globalState = Vue.observable({
minPrix2Loading: true
});
function showBtnReserver(StopReservation) {
if (StopReservation instanceof Array) {
if (StopReservation.filter(i => i).length > 0)
return false
} else {
if (StopReservation)
return false
}
return true
}
let itemHotel = {
template: "#item-hotel",
props: ['response', 'index_hotel'],
data: function () {
return {
pricesLoaded: false,
loadingPrices: false
}
},
computed: {
minPrix2Loading: function () {
return globalState.minPrix2Loading
},
isInWishlist() {
var idH = (this.response.Hotel.IdLocal !== undefined ? this.response.Hotel.IdLocal : this.response.Hotel.Id)
return wishlist.includes(idH);
},
hotel: function () {
if (this.response == null)
return null
{% if hotelSearchOnlyDetails|default('false') == 'true' %}
if (!this.pricesLoaded) {
{% if resultView == 'room-pension' %}
this.response.Price = {BoardingByRooms: []};
{% elseif resultView == 'pension-room' %}
this.response.Price = {Boarding: []};
{% elseif resultView == 'pension-combin-room' %}
this.response.Price = {Boarding: []};
{% elseif resultView == 'combin-room-pension' %}
this.response.Price = {BoardingByRooms: [{Rooms: []}]};
{% endif %}
}
{% endif %}
var photo = this.response.Hotel.Image;
if (photo == null || photo.indexOf('https://via.placeholder.com') > -1)
photo = '{{ asset('assets-commun/images/img_placeholder.jpg') }}'
var ville = this.response.Hotel.City.Name
if (this.response.Hotel.City.Region !== undefined && this.response.Hotel.City.Region != '')
ville += ', ' + this.response.Hotel.City.Region
if (this.response.Hotel.City.Zone != '')
ville += ', ' + this.response.Hotel.City.Zone
{% if enabled_hotel_stay_worldwide == 'true' %}
if (this.response.Hotel.Adress != '')
ville += "\n" + this.response.Hotel.Adress
{% endif %}
var nombreEtoiles = parseInt(this.response.Hotel.Category.Star)
{% if app.request.get('product') == "appartement" %}
var idH = this.response.Hotel.Id
{% else %}
var idH = (this.response.Hotel.IdLocal !== undefined ? this.response.Hotel.IdLocal : this.response.Hotel.Id)
{% endif %}
var paramsRouteDetails = {
// id: this.response.Hotel.SourceDetails.Hotel,
id: idH,
checkin: window.checkin_en,
nuitees: window.nuitees,
rooms: window.rooms,
slug: this.response.Hotel.Slug,
// source: this.response.Hotel.SourceDetails.Source,
{% if app.request.get('product') == "appartement" %}
source: this.response.Source,
{% else %}
source: (this.response.Hotel.IdLocal !== undefined || this.response.Source == 'local-2') ? 'all' : this.response.Source,
{% endif %}
// city: this.response.Hotel.SourceDetails.City
city: this.response.Hotel.City.Id
};
let nbrChambresPromo = []
{% if resultView == 'room-pension' %}
this.response.Price.BoardingByRooms.map((pax, idx) => {
pax.Rooms.map((room, idx) => {
room.Boarding.map(arr => {
if (!arr.surDemande && arr.BasePrice > arr.Price && (nbrChambresPromo[arr.IdRoom] === undefined || arr.disponible > nbrChambresPromo[arr.IdRoom]))
nbrChambresPromo[arr.IdRoom] = arr.disponible
})
});
});
{% elseif resultView == 'pension-room' %}
this.response.Price.Boarding.map((arr, idx) => {
arr.Pax.map((occp, idx) => {
occp.Rooms.map(function (room) {
if (!room.surDemande && room.BasePrice > room.Price && (nbrChambresPromo[room.Id] === undefined || room.disponible > nbrChambresPromo[room.Id]))
nbrChambresPromo[room.Id] = room.disponible
})
})
});
{% elseif resultView == 'pension-combin-room' %}
this.response.Price.Boarding.map((arr, idx_arr) => {
arr.Pax[0].Rooms.map((room, idx_room) => {
if (!room.surDemande && room.BasePrice > room.Price && (nbrChambresPromo[room.Id] === undefined || room.disponible > nbrChambresPromo[room.Id]))
nbrChambresPromo[room.Id] = room.Quantity
})
});
{% elseif resultView == 'combin-room-pension' %}
this.response.Price.BoardingByRooms[0].Rooms.map((room, idx_room) => {
room.Boarding.map((arr, idx_arr) => {
if (!arr.surDemande && arr.BasePrice > arr.Price && (nbrChambresPromo[arr.IdRoom] === undefined || arr.disponible > nbrChambresPromo[arr.IdRoom]))
nbrChambresPromo[arr.IdRoom] = arr.Quantity
})
});
{% endif %}
let allEtiquettes = [];
if (this.response.etiquettes !== undefined)
Object.values(this.response.etiquettes).map(etq => {
etq.nature = 'etiquette'
if (allEtiquettes.findIndex(e => e.libelle === etq.libelle) == -1) allEtiquettes.push(etq)
})
if (this.response.etiquettesSaison !== undefined)
Object.values(this.response.etiquettesSaison).map(etq => {
etq.nature = 'etiquette-saison'
if (allEtiquettes.findIndex(e => e.libelle === etq.libelle) == -1) allEtiquettes.push(etq)
})
if (this.response.etiquettesEmplacement !== undefined)
Object.values(this.response.etiquettesEmplacement).map(etq => {
etq.nature = 'etiquette-emplacement'
if (allEtiquettes.findIndex(e => e.libelle === etq.libelle) == -1) allEtiquettes.push(etq)
})
if (wishlist !== undefined)
return {
details: (details = allHotels.filter(h => h.id == idH)).length > 0 ? details[0] : null,
photo: photo,
tripAdvisor: this.response.Hotel.TripAdvisor,
Price: this.response.Price,
StopSales: this.response.StopSales !== undefined ? [this.response.StopSales.Title] : [],
description: this.response.Hotel.ShortDescription,
descriptionHotel: this.response.Hotel.HotelDescription !== undefined ? this.response.Hotel.HotelDescription : null,
recommander: this.response.Recommended,
minPrix: parseFloat(this.response.min_arrangement.min_prices).formatMoney(3, ',', ' '),
tags: this.response.Hotel.tags,
token: this.response.Token !== undefined ? this.response.Token : null,
amenagements: this.response.Hotel.Facilities,
etoile: nombreEtoiles > 0 ? nombreEtoiles : this.response.Hotel.Category.Title,
id: idH,
idville: this.response.Hotel.City.Id,
nom: this.response.Hotel.Name,
ville: ville,
autresInformations: this.response.Hotel.OtherDetails !== undefined ? this.response.Hotel.OtherDetails : {},
paramsRouteDetails: paramsRouteDetails,
nbrChambresPromo: Object.values(nbrChambresPromo).reduce((accumulator, currentValue) => {
return accumulator + currentValue
}, 0),
Recap: {
checkin: window.checkin,
nuitees: window.nuitees,
occupations: window.rooms
},
{% if app.request.get('product') == "appartement" %}
urlDetails: Routing.generate('details_appartement', paramsRouteDetails),
{% else %}
urlDetails: Routing.generate('details_hotel', paramsRouteDetails),
{% endif %}
minBasePrix: parseFloat(this.response.min_arrangement.price).formatMoney(3, ',', ' '),
minArrangement: this.response.min_arrangement.libelle,
earlyBooking: this.response.etiquettes ? Object.values(this.response.etiquettes).filter(etq => {
return etq.codeType === 6
//return etq.debutReservation
}) : [],
etiquettesEmplacement: this.response.etiquettesEmplacement ? Object.values(this.response.etiquettesEmplacement).map((etq, idx) => {
if (etq.age !== undefined)
etq.slug = 'gratuite-enfant'
else if (etq.promotion !== undefined)
etq.slug = 'promotion'
else
etq.slug = slugify(etq.libelle)
return etq;
}) : [],
etiquettes: this.response.etiquettes ? Object.values(this.response.etiquettes).sort((a, b) => {
return a.ordre > b.ordre ? 1 : -1
}).map((etq, idx) => {
if (etq.age !== undefined)
etq.slug = 'gratuite-enfant'
else if (etq.promotion !== undefined)
etq.slug = 'promotion'
else
etq.slug = slugify(etq.libelle)
etq.top = idx * 30 + 5
return etq;
}) : [],
etiquettesSaison: this.response.etiquettesSaison ? Object.values(this.response.etiquettesSaison).sort((a, b) => {
return a.ordre > b.ordre ? 1 : -1
}).map((etq, idx) => {
if (etq.age !== undefined)
etq.slug = 'gratuite-enfant'
else if (etq.promotion !== undefined)
etq.slug = 'promotion'
else
etq.slug = slugify(etq.libelle)
return etq;
}) : [],
allEtiquettes: allEtiquettes,
retrocession: this.response.retrocession,
}
},
minPrix2() {
if (this.response.min_arrangement2 !== undefined)
return {
arrangement: this.response.min_arrangement2.libelle,
chambre: this.response.min_arrangement2.chambre.libelle,
surDemande: this.response.min_arrangement2.chambre.surDemande,
msgSurDemande: this.response.min_arrangement2.chambre.msgSurDemande,
prix: parseFloat(this.response.min_arrangement2.min_prices / window.nuitees / 2).formatMoney(3, ',', ' '),
base_prix: parseFloat(this.response.min_arrangement2.price / window.nuitees / 2).formatMoney(3, ',', ' ')
}
return {
arrangement: '',
chambre: '',
surDemande: false,
disponible: 0,
prix: 0
}
}
},
mounted() {
var el = $(this.$refs.countdown)
var countDownDate = new Date(el.data('time')).getTime();
var x = setInterval(function () {
var now = new Date().getTime();
var distance = countDownDate - now;
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
el.html(days + "j " + hours + "h " + minutes + "m " + seconds + "s ");
if (distance < 0) {
clearInterval(x);
el.html("EXPIRED");
}
}, 1000);
},
methods: {
loadPrices(event) {
{% if hotelSearchOnlyDetails|default('false') == 'true' %}
if (this.pricesLoaded || this.loadingPrices) {
$(`#tarifs-hotel-${this.index_hotel}`).collapse('toggle');
return;
}
this.loadingPrices = true;
// Ajouter l'animation de loading au bouton
let loadBtn = $(event.target).closest('.btn');
let originalHtml = loadBtn.html();
loadBtn.prop('disabled', true).addClass('loading');
loadBtn.html('<span class="fa fa-spinner fa-spin" role="status" aria-hidden="true"></span> Chargement...');
// Build search parameters from cache, only updating Hotel
let searchParams = window.lastHotelSearchParams;
delete searchParams.SearchDetails.OnlyHotelDetails;
searchParams.SearchDetails.OnlyPrices = true;
searchParams.SearchDetails.Filters.Source = (this.response.Hotel.IdLocal !== undefined || this.response.Source == 'local-2') ? 'all' : this.response.Source;
if (searchParams.SearchDetails.Filters.Source != 'all') {
delete searchParams.SearchDetails.BookingDetails.City;
searchParams.SearchDetails.BookingDetails.XMLCity = this.response.Hotel.City.Id;
}
searchParams.SearchDetails.BookingDetails.Hotel = this.response.Hotel.IdLocal !== undefined ? this.response.Hotel.IdLocal : this.response.Hotel.Id;
// Make AJAX call to get prices
axios.get("{{ path('sejour_hotel_ajax_availability') }}", {
params: {
HotelSearch: utf8_to_b64(JSON.stringify(searchParams))
}
}).then(response => {
if (response.data && response.data.HotelSearch && response.data.HotelSearch[0]) {
this.pricesLoaded = true;
// Update the Price in the response using Vue.set for reactivity
this.$set(this.response, 'Price', response.data.HotelSearch[0].Price);
this.$set(this.response, 'Token', response.data.HotelSearch[0].Token);
}
this.loadingPrices = false;
// Retirer l'animation de loading
loadBtn.prop('disabled', false).removeClass('loading');
loadBtn.html(originalHtml);
// Trigger collapse after prices are loaded
$(`#tarifs-hotel-${this.index_hotel}`).collapse('show');
}).catch(error => {
console.error('Error loading prices:', error);
this.loadingPrices = false;
// Retirer l'animation de loading en cas d'erreur
loadBtn.prop('disabled', false).removeClass('loading');
loadBtn.html(originalHtml);
// Still show collapse even if error
$(`#tarifs-hotel-${this.index_hotel}`).collapse('show');
});
{% else %}
// If HOTEL_SEARCH_ONLY_DETAILS is not enabled, just toggle collapse
$(`#tarifs-hotel-${this.index_hotel}`).collapse('toggle');
{% endif %}
}
},
components: {itemPensionRoom}
}
$(document).ready(function () {
$(".invisible-content").hide();
$(document).on('click', '.btn-more', function () {
var moreLessButton = $(".invisible-content").is(':visible') ? ' Lire la suite ' : 'Reduire';
$(this).text(moreLessButton);
$(this).parent('.large-content').find(".invisible-content").toggle();
$(this).parent('.large-content').find(".visible-content").toggle();
});
});
</script>