diff --git a/admin-dev/themes/default/template/controllers/orders/_product_line.tpl b/admin-dev/themes/default/template/controllers/orders/_product_line.tpl index 17cf1903f..493123c86 100644 --- a/admin-dev/themes/default/template/controllers/orders/_product_line.tpl +++ b/admin-dev/themes/default/template/controllers/orders/_product_line.tpl @@ -147,7 +147,7 @@ {if ($can_edit)}
- {if isset($refundReqBookings) && $refundReqBookings && $data.id|in_array:$refundReqBookings && ($data.id_status == $ROOM_STATUS_CANCELLED || $data.id_status == $ROOM_STATUS_NO_SHOW)} + {if $data.id_status == $ROOM_STATUS_CANCELLED || $data.id_status == $ROOM_STATUS_NO_SHOW}
{else} -

+

{l s='No group created'}

{/if} \ No newline at end of file diff --git a/classes/order/OrderDetail.php b/classes/order/OrderDetail.php index 96f932f3a..29ba8750c 100644 --- a/classes/order/OrderDetail.php +++ b/classes/order/OrderDetail.php @@ -503,7 +503,7 @@ class OrderDetailCore extends ObjectModel $this->product_price_calculation_method, $cartServiceItem['date_from'], $cartServiceItem['date_to'] - ); + ); $itemQuantity = (isset($cartServiceItem['quantity']) ? $cartServiceItem['quantity'] : 0) * $itemNumDays; $quantity += $itemQuantity; $totalPriceTaxExcl += $itemQuantity * (isset($cartServiceItem['unit_price_tax_excl']) ? $cartServiceItem['unit_price_tax_excl'] : 0); @@ -527,7 +527,7 @@ class OrderDetailCore extends ObjectModel if (isset($quantity) && isset($unit_price_tax_excl)) { foreach ($this->tax_calculator->getTaxesAmount($unit_price_tax_excl) as $id_tax => $amount) { - $total_amount = Tools::processPriceRounding($amount, $quantity, $order->round_type, $order->round_mode); + $total_amount = $amount * $quantity; $values .= '('.(int)$order->id.','.(int)$this->id.',0,0,'.(int)$id_tax.','.(float)$amount.','.(float)$total_amount.',NOW()),'; } @@ -561,7 +561,7 @@ class OrderDetailCore extends ObjectModel foreach ($this->tax_calculator->getTaxesAmount($this->unit_price_tax_excl) as $id_tax => $amount) { - $total_amount = Tools::processPriceRounding($amount, $this->product_quantity, $order->round_type, $order->round_mode); + $total_amount = $amount * $this->product_quantity; $values .= '('.(int)$order->id.','.(int)$this->id.',0,0,'.(int)$id_tax.','.(float)$amount.','.(float)$total_amount.',NOW()),'; } diff --git a/controllers/front/CategoryController.php b/controllers/front/CategoryController.php index d98e78bbf..80ce4ded5 100644 --- a/controllers/front/CategoryController.php +++ b/controllers/front/CategoryController.php @@ -223,6 +223,28 @@ class CategoryControllerCore extends FrontController if ($booking_data = $objBookingDetail->dataForFrontSearch($bookingParams)) { $booking_data['rm_data'] = array_values($booking_data['rm_data']); + $maxAmenities = (int) Configuration::get('WK_MAX_AMENITIES_ROOM_SEARCH'); + $maxFeatures = (int) Configuration::get('WK_MAX_FEATURES_ROOM_SEARCH'); + $maxFeatureValues = (int) Configuration::get('WK_MAX_ROOM_TYPE_FEATURE_VALUES'); + foreach ($booking_data['rm_data'] as &$roomData) { + if ($maxAmenities && !empty($roomData['featured_amenities'])) { + $roomData['featured_amenities'] = array_slice($roomData['featured_amenities'], 0, $maxAmenities); + } + if (!empty($roomData['featured_features'])) { + if ($maxFeatures) { + $roomData['featured_features'] = array_slice($roomData['featured_features'], 0, $maxFeatures); + } + foreach ($roomData['featured_features'] as &$featuredFeature) { + if ($maxFeatureValues) { + $featuredFeature['values'] = array_slice($featuredFeature['values'], 0, $maxFeatureValues); + } + $featuredFeature['value'] = implode(', ', $featuredFeature['values']); + } + unset($featuredFeature); + } + } + unset($roomData); + if ($sort_by && $sort_value) { $indi_arr = array(); diff --git a/install-dev/models/install.php b/install-dev/models/install.php index dfc4df2ea..d9dabfca6 100644 --- a/install-dev/models/install.php +++ b/install-dev/models/install.php @@ -673,9 +673,9 @@ class InstallModelInstall extends InstallAbstractModel 'blocksocial', 'wkfooterblock', 'wkhotelfilterblock', + 'wkhotelroom', 'wkabouthotelblock', 'wkhotelfeaturesblock', - 'wkhotelroom', 'wktestimonialblock', 'bankwire', 'cheque', diff --git a/mails/en/‎mails/en/booking_extra_services_text.tpl b/mails/en/booking_extra_services_text.tpl similarity index 100% rename from mails/en/‎mails/en/booking_extra_services_text.tpl rename to mails/en/booking_extra_services_text.tpl diff --git a/modules/dashproducts/dashproducts.php b/modules/dashproducts/dashproducts.php index 70a8452d4..2b6cde382 100644 --- a/modules/dashproducts/dashproducts.php +++ b/modules/dashproducts/dashproducts.php @@ -255,7 +255,6 @@ class DashProducts extends Module hbd.`id_product`, hbd.`room_type_name` AS `product_name`, COUNT(hbd.`id_room`) AS `total`, - hbd.`total_price_tax_excl` AS `price`, SUM(hbd.`total_price_tax_excl`) AS `sales` FROM `'._DB_PREFIX_.'htl_booking_detail` hbd LEFT JOIN `'._DB_PREFIX_.'orders` o ON (o.`id_order` = hbd.`id_order`) @@ -285,8 +284,6 @@ class DashProducts extends Module $img = ImageManager::thumbnail($path_to_image, 'product_mini_'.$product_obj->id.'.'.$this->context->controller->imageType, 45, $this->context->controller->imageType); } - $productPrice = $product['price']; - $body[] = array( array( 'id' => 'product', @@ -297,8 +294,7 @@ class DashProducts extends Module 'id' => 'product', 'value' => ''. - Tools::htmlentitiesUTF8($product['product_name']).''. - '
'.Tools::displayPrice($productPrice), + Tools::htmlentitiesUTF8($product['product_name']).'', 'class' => 'text-center' ), array( diff --git a/modules/hotelreservationsystem/classes/HotelAmenities.php b/modules/hotelreservationsystem/classes/HotelAmenities.php index f517d891d..786c530b4 100644 --- a/modules/hotelreservationsystem/classes/HotelAmenities.php +++ b/modules/hotelreservationsystem/classes/HotelAmenities.php @@ -63,6 +63,8 @@ class HotelAmenities extends ObjectModel if (file_exists($imgFile)) { unlink($imgFile); } + Db::getInstance()->delete('htl_branch_amenity', '`amenity_id` = '.(int)$id); + Db::getInstance()->delete('htl_room_type_amenity', '`amenity_id` = '.(int)$id); return parent::delete(); } return false; diff --git a/modules/hotelreservationsystem/classes/HotelBookingDetail.php b/modules/hotelreservationsystem/classes/HotelBookingDetail.php index da06f3240..b4ae5b8ea 100644 --- a/modules/hotelreservationsystem/classes/HotelBookingDetail.php +++ b/modules/hotelreservationsystem/classes/HotelBookingDetail.php @@ -1833,9 +1833,6 @@ class HotelBookingDetail extends ObjectModel if (!$only_search_data) { if (!empty($bookingData)) { - $maxAmenities = (int) Configuration::get('WK_MAX_AMENITIES_ROOM_SEARCH'); - $maxFeatures = (int) Configuration::get('WK_MAX_FEATURES_ROOM_SEARCH'); - $maxFeatureValues = (int) Configuration::get('WK_MAX_ROOM_TYPE_FEATURE_VALUES'); foreach ($bookingData['rm_data'] as $key => $value) { // featured amenities for display in room type list $featured_amenities = HotelRoomTypeAmenities::getAmenities( @@ -1843,9 +1840,6 @@ class HotelBookingDetail extends ObjectModel $context->language->id, true ); - if ($maxAmenities) { - $featured_amenities = array_slice($featured_amenities, 0, $maxAmenities); - } if (!empty($amenities) && $amenities) { $roomAmenityIds = array_column(HotelRoomTypeAmenities::getAmenities($value['id_product']), 'id'); if (array_diff($amenities, $roomAmenityIds)) { @@ -1893,18 +1887,7 @@ class HotelBookingDetail extends ObjectModel $featuredFeatures[$roomFeature['id_feature']]['values'][] = $roomFeature['value']; } } - $featuredFeatures = array_values($featuredFeatures); - if ($maxFeatures) { - $featuredFeatures = array_slice($featuredFeatures, 0, $maxFeatures); - } - foreach ($featuredFeatures as &$featuredFeature) { - if ($maxFeatureValues) { - $featuredFeature['values'] = array_slice($featuredFeature['values'], 0, $maxFeatureValues); - } - $featuredFeature['value'] = implode(', ', $featuredFeature['values']); - } - unset($featuredFeature); - $bookingData['rm_data'][$key]['featured_features'] = $featuredFeatures; + $bookingData['rm_data'][$key]['featured_features'] = array_values($featuredFeatures); $bookingData['rm_data'][$key]['price'] = $prod_price; $bookingData['rm_data'][$key]['feature_price'] = $productFeaturePrice; $bookingData['rm_data'][$key]['price_without_reduction'] = $productPriceWithoutReduction; diff --git a/modules/hotelreservationsystem/classes/HotelCartBookingData.php b/modules/hotelreservationsystem/classes/HotelCartBookingData.php index 43b282ee2..de9156635 100644 --- a/modules/hotelreservationsystem/classes/HotelCartBookingData.php +++ b/modules/hotelreservationsystem/classes/HotelCartBookingData.php @@ -1515,7 +1515,7 @@ class HotelCartBookingData extends ObjectModel $objCartBookingData = new HotelCartBookingData(); $objRoomTypeServiceProduct = new RoomTypeServiceProduct(); $objServiceProductCartDetail = new ServiceProductCartDetail(); - $maxFeatures = (int) Configuration::get('WK_MAX_FEATURES_ROOM_SEARCH'); + $maxFeatures = (int) Configuration::get('WK_MAX_FEATURES_CHECKOUT'); $maxFeatureValues = (int) Configuration::get('WK_MAX_ROOM_TYPE_FEATURE_VALUES'); foreach ($cartRoomTypes as $prodKey => $product) { diff --git a/modules/hotelreservationsystem/classes/HotelHelper.php b/modules/hotelreservationsystem/classes/HotelHelper.php index b247b7dce..d8f9b10d2 100644 --- a/modules/hotelreservationsystem/classes/HotelHelper.php +++ b/modules/hotelreservationsystem/classes/HotelHelper.php @@ -1181,9 +1181,10 @@ class HotelHelper Configuration::updateValue('PS_MIN_BOOKING_OFFSET', 0); Configuration::updateValue('HTL_FEATURE_PRICING_PRIORITY', 'specific_date;special_day;date_range'); - Configuration::updateValue('WK_MAX_AMENITIES_ROOM_SEARCH', 0); - Configuration::updateValue('WK_MAX_FEATURES_ROOM_SEARCH', 0); - Configuration::updateValue('WK_MAX_ROOM_TYPE_FEATURE_VALUES', 0); + Configuration::updateValue('WK_MAX_AMENITIES_ROOM_SEARCH', 6); + Configuration::updateValue('WK_MAX_FEATURES_ROOM_SEARCH', 4); + Configuration::updateValue('WK_MAX_FEATURES_CHECKOUT', 0); + Configuration::updateValue('WK_MAX_ROOM_TYPE_FEATURE_VALUES', 2); Configuration::updateValue('WK_GOOGLE_ACTIVE_MAP', 0); Configuration::updateValue('WK_MAP_HOTEL_ACTIVE_ONLY', 1); @@ -2297,9 +2298,52 @@ class HotelHelper if (isset($roomTypeFeatures[$roomTypeDataDefult['name']])) { $this->saveDummyRoomTypeFeatures($product, $roomTypeFeatures[$roomTypeDataDefult['name']]); } + + // assign amenities (with featured amenities) to the room type + $roomTypeAmenities = $this->getDefaultRoomTypeAmenities(); + if (isset($roomTypeAmenities[$roomTypeDataDefult['name']])) { + $objRoomTypeAmenities = new HotelRoomTypeAmenities(); + $objRoomTypeAmenities->saveRoomTypeAmenities( + $product_id, + $roomTypeAmenities[$roomTypeDataDefult['name']]['amenities'], + $roomTypeAmenities[$roomTypeDataDefult['name']]['featured'] + ); + } } } + /** + * Return the amenity ids (and the featured ones) of each demo room type, keyed by the room type name. + * Amenity ids are the ids of the default amenities created by insertHotelCommonAmenities(). + * + * @return array + */ + protected function getDefaultRoomTypeAmenities() + { + return array( + 'General Rooms' => array( + // Internet Access Free, Power Backup, Parking, NewsPaper In Lobby, Laundry Service, Gardens, Room Service, Welcome Drinks + 'amenities' => array(10, 25, 48, 12, 24, 55, 38, 14, 11), + 'featured' => array(10, 25, 48, 12, 24, 55, 38, 14), + ), + 'Delux Rooms' => array( + // + Bar / Lounge, Transfer Available + 'amenities' => array(10, 25, 48, 38, 14, 24, 55, 99, 12, 11), + 'featured' => array(10, 25, 38, 14, 48, 24, 55, 99), + ), + 'Executive Rooms' => array( + // + Health Club / Gym, Multi Cuisine Restaurant + 'amenities' => array(10, 25, 48, 38, 14, 24, 12, 69, 99, 100), + 'featured' => array(10, 38, 14, 69, 100, 48, 25, 24), + ), + 'Luxury Rooms' => array( + // + Car Rental, Swimming Pool, Jacuzzi, Spa Services + 'amenities' => array(10, 25, 48, 38, 14, 24, 40, 69, 93, 94, 87, 99, 100), + 'featured' => array(10, 38, 93, 94, 87, 100, 69, 99), + ), + ); + } + /** * Return the features (and their values) of each demo room type, keyed by the room type name. * diff --git a/modules/hotelreservationsystem/classes/HotelReservationSystemDb.php b/modules/hotelreservationsystem/classes/HotelReservationSystemDb.php index 5b3126d7b..32542bc30 100644 --- a/modules/hotelreservationsystem/classes/HotelReservationSystemDb.php +++ b/modules/hotelreservationsystem/classes/HotelReservationSystemDb.php @@ -152,8 +152,7 @@ class HotelReservationSystemDb `date_add` datetime NOT NULL, `date_upd` datetime NOT NULL, PRIMARY KEY (`id_branch_amenity`), - CONSTRAINT `fk_htl_branch_amenity_amenity` FOREIGN KEY (`amenity_id`) - REFERENCES `"._DB_PREFIX_."htl_amenity` (`id_amenity`) ON DELETE CASCADE + KEY `amenity_id` (`amenity_id`) ) ENGINE="._MYSQL_ENGINE_." DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;", "CREATE TABLE IF NOT EXISTS `"._DB_PREFIX_."htl_room_type_amenity` ( @@ -165,8 +164,7 @@ class HotelReservationSystemDb `date_upd` datetime NOT NULL, PRIMARY KEY (`id_room_type_amenity`), KEY `id_product` (`id_product`), - CONSTRAINT `fk_htl_room_type_amenity_amenity` FOREIGN KEY (`amenity_id`) - REFERENCES `"._DB_PREFIX_."htl_amenity` (`id_amenity`) ON DELETE CASCADE + KEY `amenity_id` (`amenity_id`) ) ENGINE="._MYSQL_ENGINE_." DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;", "CREATE TABLE IF NOT EXISTS `"._DB_PREFIX_."htl_cart_booking_data` ( diff --git a/modules/hotelreservationsystem/controllers/admin/AdminHotelGeneralSettingsController.php b/modules/hotelreservationsystem/controllers/admin/AdminHotelGeneralSettingsController.php index f978ca93e..f00149fbe 100644 --- a/modules/hotelreservationsystem/controllers/admin/AdminHotelGeneralSettingsController.php +++ b/modules/hotelreservationsystem/controllers/admin/AdminHotelGeneralSettingsController.php @@ -166,7 +166,7 @@ class AdminHotelGeneralSettingsController extends ModuleAdminController 'hint' => $this->l('Enable to display hotels list on the contact us page.'), ), 'WK_MAX_AMENITIES_ROOM_SEARCH' => array( - 'title' => $this->l('Maximum featured amenities in room search'), + 'title' => $this->l('Max featured amenities in room search'), 'hint' => $this->l('Maximum number of featured amenities to display for each room type on the front office room search page.'), 'desc' => $this->l('Set to 0 to display all featured amenities.'), 'type' => 'text', @@ -175,7 +175,7 @@ class AdminHotelGeneralSettingsController extends ModuleAdminController 'default' => '0', ), 'WK_MAX_FEATURES_ROOM_SEARCH' => array( - 'title' => $this->l('Maximum featured features in room search'), + 'title' => $this->l('Max Featured room type features on room search page'), 'hint' => $this->l('Maximum number of featured features to display for each room type on the front office room search page.'), 'desc' => $this->l('Set to 0 to display all featured features.'), 'type' => 'text', @@ -183,9 +183,18 @@ class AdminHotelGeneralSettingsController extends ModuleAdminController 'class' => 'fixed-width-xl', 'default' => '0', ), + 'WK_MAX_FEATURES_CHECKOUT' => array( + 'title' => $this->l('Max Featured room type features on Checkout page'), + 'hint' => $this->l('Maximum number of featured features to display for each room type on the front office checkout page.'), + 'desc' => $this->l('Set to 0 to display all featured features.'), + 'type' => 'text', + 'cast' => 'intval', + 'class' => 'fixed-width-xl', + 'default' => '0', + ), 'WK_MAX_ROOM_TYPE_FEATURE_VALUES' => array( - 'title' => $this->l('Maximum room type feature values per featured feature'), - 'hint' => $this->l('Maximum number of room type feature values to display for each featured feature on the front office room search and order pages. For example, if the featured feature Bed Type has the values Single, Double and Queen and this is set to 2, only "Single, Double" is displayed.'), + 'title' => $this->l('Max display values for room type Featured features'), + 'hint' => $this->l('Maximum number of room type feature values to display for each featured feature in room search results and orders. For example, if the featured feature Bed Type has the values Single, Double, and Queen, and this setting is set to 2, only Single, Double will be displayed.'), 'desc' => $this->l('Set to 0 to display all values of each featured feature.'), 'type' => 'text', 'cast' => 'intval', @@ -562,6 +571,9 @@ class AdminHotelGeneralSettingsController extends ModuleAdminController if (!Validate::isUnsignedInt(Tools::getValue('WK_MAX_FEATURES_ROOM_SEARCH'))) { $this->errors[] = $this->l('Maximum featured features in room search is invalid. Enter 0 or a positive number.'); } + if (!Validate::isUnsignedInt(Tools::getValue('WK_MAX_FEATURES_CHECKOUT'))) { + $this->errors[] = $this->l('Maximum featured features in checkout is invalid. Enter 0 or a positive number.'); + } if (!Validate::isUnsignedInt(Tools::getValue('WK_MAX_ROOM_TYPE_FEATURE_VALUES'))) { $this->errors[] = $this->l('Maximum room type feature values per featured feature is invalid. Enter 0 or a positive number.'); } diff --git a/modules/hotelreservationsystem/hotelreservationsystem.php b/modules/hotelreservationsystem/hotelreservationsystem.php index 94b683e54..9cb776db0 100644 --- a/modules/hotelreservationsystem/hotelreservationsystem.php +++ b/modules/hotelreservationsystem/hotelreservationsystem.php @@ -610,6 +610,7 @@ class HotelReservationSystem extends Module 'WK_DISPLAY_CONTACT_PAGE_HOTEL_LIST', 'WK_MAX_AMENITIES_ROOM_SEARCH', 'WK_MAX_FEATURES_ROOM_SEARCH', + 'WK_MAX_FEATURES_CHECKOUT', 'WK_MAX_ROOM_TYPE_FEATURE_VALUES', 'QLO_HEADER_MEDIA_TYPE', 'QLO_HEADER_CONTENT_ALIGN', diff --git a/modules/qlocleaner/qlocleaner.php b/modules/qlocleaner/qlocleaner.php index 2cb11959f..011615f49 100644 --- a/modules/qlocleaner/qlocleaner.php +++ b/modules/qlocleaner/qlocleaner.php @@ -686,8 +686,8 @@ class QloCleaner extends Module array('htl_testimonials_block_data_lang', 'id_testimonial_block', 'htl_testimonials_block_data', 'id_testimonial_block'), array('htl_branch_info_lang', 'id_lang', 'lang', 'id_lang'), array('htl_branch_info_lang', 'id', 'htl_branch_info', 'id'), - array('htl_features_lang', 'id_lang', 'lang', 'id_lang'), - array('htl_features_lang', 'id', 'htl_features', 'id'), + array('htl_amenity_lang', 'id_lang', 'lang', 'id_lang'), + array('htl_amenity_lang', 'id_amenity', 'htl_amenity', 'id_amenity'), array('htl_room_type_feature_pricing', 'id_product', 'product', 'id_product'), array('htl_room_type_feature_pricing_restriction', 'id_feature_price', 'htl_room_type_feature_pricing', 'id_feature_price'), array('htl_room_type_feature_pricing_group', 'id_group', 'group', 'id_group'), diff --git a/modules/qlogooglehotelconnector/controllers/admin/AdminGoogleHotelLogsController.php b/modules/qlogooglehotelconnector/controllers/admin/AdminGoogleHotelLogsController.php index f2e44715e..7015a13b5 100644 --- a/modules/qlogooglehotelconnector/controllers/admin/AdminGoogleHotelLogsController.php +++ b/modules/qlogooglehotelconnector/controllers/admin/AdminGoogleHotelLogsController.php @@ -36,12 +36,12 @@ class AdminGoogleHotelLogsController extends ModuleAdminController // Every QghcApiLog::TYPE_* must have an entry here, or it shows as its raw // value in the filter dropdown, the list column, and the detail view. $this->typeLabels = array( - QghcApiLog::TYPE_ARI_FULL => 'Full Availability & Rates Update', - QghcApiLog::TYPE_ARI_CHANGE => 'Availability & Rates Change Update', - QghcApiLog::TYPE_GOOGLE_STATUS => 'Google Status', - QghcApiLog::TYPE_CONNECTION => 'Connection', - QghcApiLog::TYPE_DELETE_CONNECTION => 'Delete Connection', - QghcApiLog::TYPE_HOTEL_LIST_FEED => 'Property Detail', + QghcApiLog::TYPE_ARI_FULL => $this->l('Full Availability & Rates Update'), + QghcApiLog::TYPE_ARI_CHANGE => $this->l('Availability & Rates Change Update'), + QghcApiLog::TYPE_GOOGLE_STATUS => $this->l('Google Status'), + QghcApiLog::TYPE_CONNECTION => $this->l('Connection'), + QghcApiLog::TYPE_DELETE_CONNECTION => $this->l('Delete Connection'), + QghcApiLog::TYPE_HOTEL_LIST_FEED => $this->l('Properties Details'), ); $this->bootstrap = true; diff --git a/modules/qlogooglehotelconnector/qlogooglehotelconnector.php b/modules/qlogooglehotelconnector/qlogooglehotelconnector.php index 47296fe35..10f66c56f 100644 --- a/modules/qlogooglehotelconnector/qlogooglehotelconnector.php +++ b/modules/qlogooglehotelconnector/qlogooglehotelconnector.php @@ -903,7 +903,7 @@ class QloGoogleHotelConnector extends Module $oldStatus = (int)$oldRoom->id_status; $newStatus = isset($newRoomInfo['id_status']) ? (int)$newRoomInfo['id_status'] : $oldStatus; - if (($newStatus !== HotelRoomInformation::STATUS_TEMPORARY_INACTIVE) && ($oldStatus !== $newStatus)) { + if ($oldStatus !== $newStatus) { $objHotelRoomInfo = new HotelRoomInformation(); $roomInfoArray = $objHotelRoomInfo->getHotelRoomInfoByProductId((int)$oldRoom->id_product); if (empty($roomInfoArray)) { diff --git a/modules/wkabouthotelblock/views/css/WkAboutHotelBlockFront.css b/modules/wkabouthotelblock/views/css/WkAboutHotelBlockFront.css index bfe15adaa..332b27df1 100644 --- a/modules/wkabouthotelblock/views/css/WkAboutHotelBlockFront.css +++ b/modules/wkabouthotelblock/views/css/WkAboutHotelBlockFront.css @@ -20,8 +20,11 @@ * @license https://opensource.org/license/osl-3-0-php Open Software License version 3.0 */ -.htlInterior-owlCarousel .owl-stage-outer { - border: 1px solid #ccc; +@media (max-width: 767px) { + .htlInterior-owlCarousel .owl-carousel { + width: 100%; + margin: 0; + } } .interiorImgWrapper { width: 100%; @@ -46,32 +49,24 @@ height: 100%; object-fit: cover; } -.htlInterior-owlCarousel .owl-prev, .htlInterior-owlCarousel .owl-next{ - font-size: 40px; - font-weight: 200; - position: absolute; - top: 0; - bottom: 0; - z-index: 10; -} -.htlInterior-owlCarousel .owl-prev { - left: 0; -} -.htlInterior-owlCarousel .owl-next { - right: 0; -} .nav-direction-wrapper{ - display: table; - height: 100%; + display: block; } .nav-direction-primary { - display: table-cell; - vertical-align: middle; + display: block; } .nav-direction-secondary { - padding: 40px 18px; - opacity: 0.85; - background-color: #ffffff; + background: rgba(0, 0, 0, 0.4); + color: #fff; + border-radius: 2px; + padding: 8px 14px; + font-size: 20px; + line-height: 1; + transition: background 0.2s; +} +.htlInterior-owlCarousel .owl-prev:hover .nav-direction-secondary, +.htlInterior-owlCarousel .owl-next:hover .nav-direction-secondary { + background: rgba(0, 0, 0, 0.65); } .interiorHoverBlockWrapper { position: absolute; @@ -79,7 +74,7 @@ right: 0; top: 0; bottom: 0; - background-image: url("../img/black-opacity-5.png"); + background-color: rgba(0, 0, 0, 0.5); cursor: pointer; display: none; } @@ -94,4 +89,88 @@ font-size: 50px; text-align: center; vertical-align: middle; -} \ No newline at end of file +} + +/* gallery: pages of 8 square photos (4 x 2) with dots below */ +.htlInterior-owlCarousel .owl-stage-outer { + border: 0; +} +.interiorImgWrapper { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 8px; + height: auto; +} +.interiorbox { + padding-bottom: 100%; +} +.interiorboxInner { + border: 0; + border-radius: 3px; +} +.htlInterior-owlCarousel .owl-dots { + display: flex; + justify-content: center; + gap: 6px; + margin-top: 24px; +} +.htlInterior-owlCarousel .owl-dots .owl-dot span { + display: block; + width: 7px; + height: 7px; + margin: 0; + border-radius: 50%; + background: #C4C4C4; +} +.htlInterior-owlCarousel .owl-dots .owl-dot.active span { + background: #333; +} +/* touch screens have no hover, so always show the zoom badge */ +@media (hover: none) { + #hotelInteriorBlock .interiorbox::after { + content: "\f00e"; + font-family: "FontAwesome"; + position: absolute; + right: 8px; + top: 8px; + width: 28px; + height: 28px; + border-radius: 50%; + background: rgba(0, 0, 0, .45); + color: #fff; + font-size: 14px; + line-height: 28px; + text-align: center; + pointer-events: none; + } +} + +/* gallery lightbox: square photo, dark overlay, thumbnail strip with round prev/next at the bottom */ +html body .htl-gallery-fancybox .fancybox-skin, html body .htl-light-fancybox .fancybox-skin { border-radius: 5px; } +html body .htl-gallery-fancybox .fancybox-skin { padding: 0 !important; background: transparent; border-radius: 5px; box-shadow: none; } +html body .htl-gallery-fancybox .fancybox-outer, html body .htl-gallery-fancybox .fancybox-inner { border-radius: 5px; overflow: hidden; } +html body .htl-gallery-fancybox .fancybox-image { border-radius: 5px; } +html body .htl-light-fancybox .fancybox-title-outside-wrap { position: static; display: table; width: auto; margin: 14px auto 0; padding: 6px 20px; border-radius: 16px; background: #2b2b2b; font-size: 13px; font-weight: 700; line-height: 1.4; color: #fff; text-align: center; } +html body .htl-gallery-fancybox .fancybox-title-outside-wrap { position: static; display: table; width: auto; margin: 14px auto 0; padding: 6px 20px; border: 1px solid rgba(255, 255, 255, .35); border-radius: 16px; background: #111; font-size: 13px; font-weight: 700; line-height: 1.4; color: #fff; text-align: center; } +.htl-gal-thumbs { position: fixed; left: 0; right: 0; bottom: 49px; z-index: 8040; display: flex; align-items: center; gap: 16px; padding: 0 28px; } +.htl-gal-thumbs__track { flex: 1 1 auto; display: flex; gap: 12px; overflow-x: auto; scroll-behavior: smooth; scrollbar-width: none; padding: 2px 0; } +.htl-gal-thumbs__track::-webkit-scrollbar { display: none; } +.htl-gal-thumbs__item { flex: 0 0 auto; width: 96px; height: 96px; padding: 0; border: 2px solid transparent; border-radius: 2px; background: #000; overflow: hidden; opacity: .6; cursor: pointer; transition: opacity .2s ease, border-color .2s ease; } +.htl-gal-thumbs__item img { display: block; width: 100%; height: 100%; object-fit: cover; } +.htl-gal-thumbs__item:hover, .htl-gal-thumbs__item.is-active { opacity: 1; } +.htl-gal-thumbs__item.is-active { border-color: #fff; } +.htl-gal-thumbs__nav { flex: 0 0 auto; display: flex; align-items: center; justify-content: center; padding: 8px 15px; border: 0; border-radius: 50%; background: #fff; color: #333; font-size: 22px; line-height: 1; box-shadow: 0 2px 10px rgba(0, 0, 0, .3); cursor: pointer; transition: transform .2s ease; } +.htl-gal-thumbs__nav i { display: block; line-height: 1; } +@media (max-width: 767px) { + .htl-gal-thumbs { bottom: 20px; padding: 0 12px; gap: 8px; } + .htl-gal-thumbs__item { width: 60px; height: 60px; } + .htl-gal-thumbs__nav { width: 36px; height: 36px; font-size: 20px; } + html body .htl-gallery-fancybox .fancybox-close { top: 8px; right: 8px; } +} +html body .fancybox-overlay.htl-gallery-overlay { opacity: 1 !important; background: rgba(43, 43, 43, 0.95) !important; } + +/* the theme's a:focus outline would cover half of the photo after a click on next/prev, keep it for keyboard users only */ +html body .htl-light-fancybox .fancybox-nav:focus:not(:focus-visible), +html body .htl-gallery-fancybox .fancybox-nav:focus:not(:focus-visible) { + outline: 0; +} diff --git a/modules/wkabouthotelblock/views/js/WkAboutHotelBlockFront.js b/modules/wkabouthotelblock/views/js/WkAboutHotelBlockFront.js index 331cd5051..40c2a1af8 100644 --- a/modules/wkabouthotelblock/views/js/WkAboutHotelBlockFront.js +++ b/modules/wkabouthotelblock/views/js/WkAboutHotelBlockFront.js @@ -23,26 +23,19 @@ $(document).ready(function(){ $('.htlInterior-owlCarousel .owl-carousel').owlCarousel({ loop:true, - nav:true, - navSpeed:1000, - navText:['',''], - dots:false, + nav:false, + dots:true, items: 1, + margin: 8, + slideBy: 'page', + responsive: {576: {items: 2}}, autoHeight:true, autoplay:true, autoplaySpeed:1000, autoplayTimeout:5000, autoplayHoverPause:true, responsiveClass:true, - rtl: language_is_rtl, - responsive:{ - 1200:{ - items:3 - }, - 480:{ - items:2 - }, - } + rtl: language_is_rtl }); $('.interiorbox').on('mouseenter', function(){ @@ -52,20 +45,123 @@ $(document).ready(function(){ $(this).find('div.interiorHoverBlockWrapper').hide(); }); - $("div.interiorbox").fancybox({ - autoDimensions: true, - autoScale: true, - autoSize: true, - centerOnScroll: true, - height: 'auto', - scrolling: 'auto', - width: 'auto', - maxWidth: 700, - 'hideOnContentClick': false, - helpers: { - overlay: { - locked: false - } - } - }); -}); \ No newline at end of file + // gallery lightbox: fancybox with a thumbnail strip and round prev/next buttons at the bottom + var $thumbs = null; + + function buildThumbs() { + var group = $.fancybox.group || []; + if (group.length < 2) { + return; + } + $thumbs = $('
'); + var $track = $thumbs.find('.htl-gal-thumbs__track'); + $.each(group, function(i, item) { + $('') + .attr('aria-label', (i + 1) + ' / ' + group.length) + .append($('').attr('src', item.href)) + .on('click', function() { this.blur(); $.fancybox.jumpto(i); }) + .appendTo($track); + }); + $thumbs.find('.htl-gal-thumbs__prev').on('click', function() { this.blur(); $.fancybox.prev(); }); + $thumbs.find('.htl-gal-thumbs__next').on('click', function() { this.blur(); $.fancybox.next(); }); + $thumbs.appendTo('body'); + } + + function markActiveThumb() { + if (!$thumbs) { + return; + } + var $items = $thumbs.find('.htl-gal-thumbs__item').removeClass('is-active'); + var $active = $items.eq($.fancybox.current.index).addClass('is-active'); + var track = $thumbs.find('.htl-gal-thumbs__track').get(0); + if ($active.length && track) { + track.scrollLeft = $active.get(0).offsetLeft - (track.clientWidth - $active.outerWidth()) / 2; + } + } + + // options of the dark gallery with a thumbnail strip + var thumbsGalleryOptions = { + padding: 0, + margin: [48, 48, 190, 48], + wrapCSS: 'htl-gallery-fancybox', + arrows: false, + helpers: {overlay: {locked: false, css: {background: 'rgba(43, 43, 43, 0.9)'}}}, + beforeLoad: function() { + var compact = window.innerWidth < 768 || window.innerHeight < 500; + this.margin = window.innerHeight < 500 ? [36, 12, 84, 12] : (compact ? [48, 12, 110, 12] : [48, 48, 190, 48]); + }, + afterLoad: function() { + // photos are shown as large as the screen allows (up to 589px), not at their natural size + var smallW = window.innerWidth < 768; + var shortH = window.innerHeight < 500; + var maxH = Math.min(window.innerHeight - (shortH ? 120 : (smallW ? 158 : 238)), 589); + var maxW = window.innerWidth - (shortH || smallW ? 24 : 96); + var ratio = this.width / this.height; + var height = maxH; + var width = height * ratio; + if (width > maxW) { + width = maxW; + height = width / ratio; + } + this.width = Math.round(width); + this.height = Math.round(height); + }, + beforeShow: function() { + $('.fancybox-overlay').addClass('htl-gallery-overlay'); + if (!$thumbs) { + buildThumbs(); + } + }, + afterShow: markActiveThumb, + afterClose: function() { + if ($thumbs) { + $thumbs.remove(); + $thumbs = null; + } + } + }; + + // options of the light gallery with the next and previous arrows on the photo + var lightGalleryOptions = { + wrapCSS: 'htl-light-fancybox', + maxWidth: 700, + nextEffect: 'fade', + prevEffect: 'fade', + helpers: {overlay: {locked: false}} + }; + + /** + * Opens the photos of a slider in a lightbox when one is clicked. + * Usage: $('.owl-carousel').interiorBoxGallery({thumbs: true}); + * thumbs true: dark gallery with a thumbnail strip, false: light gallery with arrows. + */ + $.fn.interiorBoxGallery = function(options) { + var settings = $.extend({thumbs: true, itemSelector: '.interiorbox[href]'}, options); + + return this.each(function() { + var $slider = $(this); + // photos are listed once, the slider also holds cloned copies when it loops + $slider.on('click', settings.itemSelector, function(e) { + e.preventDefault(); + var items = []; + var index = 0; + var clicked = $(e.currentTarget).attr('href'); + $slider.find('.owl-item:not(.cloned) ' + settings.itemSelector).not('.interiorbox-filler').each(function(i) { + items.push({href: $(this).attr('href'), title: $(this).attr('title') || ''}); + if ($(this).attr('href') === clicked) { + index = i; + } + }); + $.fancybox.open(items, $.extend(true, { + index: index, + type: 'image', + openEffect: 'fade', + closeEffect: 'fade', + helpers: {title: {type: 'outside'}} + }, settings.thumbs ? thumbsGalleryOptions : lightGalleryOptions)); + }); + }); + }; + + $('.htlInterior-owlCarousel .owl-carousel').interiorBoxGallery({thumbs: true}); +}); diff --git a/modules/wkabouthotelblock/views/templates/hook/hotelInteriorBlock.tpl b/modules/wkabouthotelblock/views/templates/hook/hotelInteriorBlock.tpl index 71ae109f1..646d5b7f8 100644 --- a/modules/wkabouthotelblock/views/templates/hook/hotelInteriorBlock.tpl +++ b/modules/wkabouthotelblock/views/templates/hook/hotelInteriorBlock.tpl @@ -44,12 +44,11 @@
{/if} - {assign var='intImgIteration' value=$smarty.foreach.intImg.iteration} {/foreach} - {if $intImgIteration%3} - {assign var='intImgLeft' value=3-($intImgIteration%3)} - {for $foo=1 to $intImgLeft} -
-
- Default Image -
-
- {/for} -
- {/if}
diff --git a/modules/wkabouthotelblock/wkabouthotelblock.php b/modules/wkabouthotelblock/wkabouthotelblock.php index 0a6faa5f0..3fbdb98e9 100644 --- a/modules/wkabouthotelblock/wkabouthotelblock.php +++ b/modules/wkabouthotelblock/wkabouthotelblock.php @@ -47,6 +47,7 @@ class WkAboutHotelBlock extends Module public function hookDisplayHome() { + $this->context->controller->addJqueryPlugin('fancybox'); $this->context->controller->addCSS(_PS_JS_DIR_.'owl-carousel/assets/owl.carousel.min.css'); $this->context->controller->addCSS(_PS_JS_DIR_.'owl-carousel/assets/owl.theme.default.min.css'); $this->context->controller->addJS(_PS_JS_DIR_.'owl-carousel/owl.carousel.min.js'); @@ -58,6 +59,13 @@ class WkAboutHotelBlock extends Module $objHtlInteriorImg = new WkHotelInteriorImage(); $InteriorImg = $objHtlInteriorImg->getHotelInteriorImg(1); + // every slide shows 4 photos, so the last slide is completed with photos from the start + if ($InteriorImg && ($missing = (4 - count($InteriorImg) % 4) % 4)) { + foreach (array_slice($InteriorImg, 0, $missing) as $filler) { + $filler['is_filler'] = 1; + $InteriorImg[] = $filler; + } + } $this->context->smarty->assign( array( diff --git a/modules/wkhotelfeaturesblock/views/css/wkHotelFeaturesBlockFront.css b/modules/wkhotelfeaturesblock/views/css/wkHotelFeaturesBlockFront.css index 7e80c83b4..05cafee55 100644 --- a/modules/wkhotelfeaturesblock/views/css/wkHotelFeaturesBlockFront.css +++ b/modules/wkhotelfeaturesblock/views/css/wkHotelFeaturesBlockFront.css @@ -62,4 +62,12 @@ .amenity_desc_hr { border-top: 1px solid #333333; width: 60px; +} +@media (max-width: 767px) { + #hotelAmenitiesBlock .visible-xs .amenity_img_secondary { + margin: 0 15px; + } + #hotelAmenitiesBlock .visible-xs .amenity_desc_secondary { + padding: 30px 15px; + } } \ No newline at end of file diff --git a/modules/wkhotelfeaturesblock/views/js/wkHotelFeaturesBlockFront.js b/modules/wkhotelfeaturesblock/views/js/wkHotelFeaturesBlockFront.js index 6be596818..6557ea3d7 100644 --- a/modules/wkhotelfeaturesblock/views/js/wkHotelFeaturesBlockFront.js +++ b/modules/wkhotelfeaturesblock/views/js/wkHotelFeaturesBlockFront.js @@ -37,6 +37,12 @@ function setAmenitiesWrapperHeight() { function setAmenitiesDescContHeight() { $('.amenity_desc_cont').each(function () { + // on mobile the image and text stack instead of sitting side by side, + // so matching the text box's height to the combined row height leaves a large blank gap + if ($(this).closest('.visible-xs').length) { + $(this).css('height', 'auto'); + return; + } var amenityDescParentHeight = $(this).parent('div.amenity_content').height(); $(this).css('height', amenityDescParentHeight); }); diff --git a/modules/wkhotelfilterblock/views/css/wkhotelfilterblock.css b/modules/wkhotelfilterblock/views/css/wkhotelfilterblock.css index 5c2e5cdbd..292ca4cca 100644 --- a/modules/wkhotelfilterblock/views/css/wkhotelfilterblock.css +++ b/modules/wkhotelfilterblock/views/css/wkhotelfilterblock.css @@ -58,7 +58,7 @@ .layered_filt { - margin-bottom: 5px; + margin-bottom: 8px; } .layered_filt_category @@ -111,4 +111,11 @@ #filter_price_silder.ui-widget-content { border: none; -} \ No newline at end of file +} + +.layered_filt_label { + display: block; + margin: 0; + font-weight: normal; + cursor: pointer; +} diff --git a/modules/wkhotelfilterblock/views/js/wkhotelfilterblock.js b/modules/wkhotelfilterblock/views/js/wkhotelfilterblock.js index bfa546c65..4c1dd5f6b 100644 --- a/modules/wkhotelfilterblock/views/js/wkhotelfilterblock.js +++ b/modules/wkhotelfilterblock/views/js/wkhotelfilterblock.js @@ -132,6 +132,7 @@ $(document).ready(function() triggerFilter(1, 0, 0, 0); $('.filter').on('click', function() { + $(this).parent().toggleClass('checked', this.checked); triggerFilter(); }); @@ -202,4 +203,47 @@ $(document).ready(function() }); return 1; } + var $conts = $('#filter_results > .col-sm-12 > .layered_filter_cont'); + if ($conts.length) { + var $nav = $('
'); + $conts.each(function () { + $nav.append($('').text($(this).find('.lf_headingmain_wrapper span').first().text()).append('')); + }); + $('#filter_results > .col-sm-12').prepend($nav); + + var $sheet = $('
' + mfSortByTxt + '
'); + $('.sort_result').each(function () { + $sheet.find('ul').append($('
  • ').text($(this).text()).data('source', $(this))); + }); + var $bar = $('
    '); + $('body').append($sheet, $bar); + + function selectTab(i) { + $nav.children().removeClass('mf_active').eq(i).addClass('mf_active'); + $conts.removeClass('mf_active').eq(i).addClass('mf_active'); + } + selectTab(0); + + function updateCounts() { + var total = 0; + $conts.each(function (i) { + var n = $(this).find('input.filter:checked').length; + var v = $(this).find('#filter_price_silder').length ? $('#filter_price_silder').slider('values') : 0; + n += v && (v[0] != min_price || v[1] != max_price) ? 1 : 0; + total += n; + $nav.children().eq(i).children('b').text(n || ''); + }); + $bar.find('.mf_filter b').text(total || ''); + } + $(document).on('click change slidechange', '#filter_results', function () { setTimeout(updateCounts, 50); }); + + $nav.on('click', '.mf_tab', function () { selectTab($(this).index()); }); + $bar.find('.mf_filter').on('click', function () { $('body').addClass('mf_filter_open'); }); + $bar.find('.mf_sort').on('click', function () { $sheet.addClass('mf_open'); }); + $('.mf_back, .mf_apply').on('click', function () { $('body').removeClass('mf_filter_open'); }); + $('.mf_clear_all').on('click', function () { $('.clear_filter').trigger('click'); }); + $sheet.on('click', function (e) { if (e.target === this || $(e.target).is('button')) $sheet.removeClass('mf_open'); }); + $sheet.on('click', 'li', function () { $(this).addClass('mf_selected').siblings().removeClass('mf_selected').end().data('source').trigger('click'); $sheet.removeClass('mf_open'); }); + $sheet.find('li').first().addClass('mf_selected'); + } }); \ No newline at end of file diff --git a/modules/wkhotelfilterblock/views/templates/hook/htlfilterblock.tpl b/modules/wkhotelfilterblock/views/templates/hook/htlfilterblock.tpl index 0fab3ecf3..007862b39 100644 --- a/modules/wkhotelfilterblock/views/templates/hook/htlfilterblock.tpl +++ b/modules/wkhotelfilterblock/views/templates/hook/htlfilterblock.tpl @@ -22,6 +22,12 @@ {block name='room_types_filters_block'}
    + {* mobile only: header of the full screen filters panel *} +
    + + {l s='Filters' mod='wkhotelfilterblock'} + +
    {block name='room_types_price_filter'} {if isset($config) && $config['SHOW_PRICE_FILTER']} @@ -61,8 +67,10 @@
    {foreach $all_amenities as $amenity}
    - - {$amenity.name} +
    {/foreach}
    @@ -86,8 +94,10 @@
    {foreach $feature.values as $featureValue}
    - - {$featureValue.value|escape:'html':'UTF-8'} +
    {/foreach}
    @@ -96,6 +106,9 @@ {/if} {/block}
    + {block name='room_types_filters_mobile_apply'} + + {/block}
    {block name='room_types_filters_js_vars'} {strip} @@ -108,6 +121,9 @@ {addJsDef max_price = $max_price} {addJsDef warning_num = $warning_num} + {addJsDefL name=mfSortTxt}{l s='Sort' js=1 mod='wkhotelfilterblock'}{/addJsDefL} + {addJsDefL name=mfSortByTxt}{l s='Sort by' js=1 mod='wkhotelfilterblock'}{/addJsDefL} + {addJsDefL name=mfFilterTxt}{l s='Filter' js=1 mod='wkhotelfilterblock'}{/addJsDefL} {addJsDefL name=viewMoreTxt}{l s='View More' js=1 mod='wkhotelfilterblock'}{/addJsDefL} {addJsDefL name=bookNowTxt}{l s='Book Now' js=1 mod='wkhotelfilterblock'}{/addJsDefL} {/strip} diff --git a/modules/wkhotelroom/views/css/WkHotelRoomBlockFront.css b/modules/wkhotelroom/views/css/WkHotelRoomBlockFront.css index d3776d0e5..3a8228f5d 100644 --- a/modules/wkhotelroom/views/css/WkHotelRoomBlockFront.css +++ b/modules/wkhotelroom/views/css/WkHotelRoomBlockFront.css @@ -50,17 +50,24 @@ float :right; } } +@media (min-width: 768px) and (max-width: 991px) { + #hotelRoomsBlock .col-md-6 { + width: 50%; + float: left; + } +} @media (max-width: 530px) { + #hotelRoomsBlock .col-md-6 > a img.width-100 { + width: 100%; + margin: 0; + } .hotelRoomDescContainer{ - padding: 10px; + padding: 15px 0px; } .wk_roomType_price_type{ font-size: 16px; font-weight: 400; } - .htlRoomTypeNameText { - width: 100%; - } .room_type_old_price { width: 100%; @@ -91,12 +98,231 @@ a.htlRoomTypeBookNow { text-transform: capitalize; } -.btn.htlRoomTypeBookNow:hover{ - border: 1px solid #333333; -} .room_type_old_price { text-decoration: line-through; color:#555555; font-size:14px; -} \ No newline at end of file +} + +/* room type cards slider */ +.htlRoom-owlCarousel .owl-carousel { + padding: 0 0 6px; +} +.htlRoomCard { + background: #fff; + border: 1px solid #E5E5E5; + border-radius: 4px; + overflow: hidden; + box-shadow: 0 1px 4px rgba(0, 0, 0, .06); +} +.htlRoomCardImg { + display: block; + aspect-ratio: 4 / 3; + overflow: hidden; +} +.htlRoomCardImg img { + width: 100%; + height: 100%; + object-fit: cover; +} +.htlRoomCardBody { + padding: 16px; +} +.htlRoomCardBody .htlRoomTypeNameText { + float: none; + margin: 0 0 12px; + font-size: 22px; +} +.htlRoomCardFeatured { + padding: 12px 0; + overflow: hidden; + white-space: nowrap; + color: #555; + font-size: 14px; +} +.htlRoomCardFeatured img.htlRoomFeatureImg { + display: inline-block; + width: 16px; + height: 16px; + max-width: 16px; + margin-right: 4px; + object-fit: contain; + vertical-align: -3px; +} +.htlRoomCardAmen > span img.htlRoomAmenityImg { + width: 18px; + height: 18px; + max-width: 18px; + object-fit: contain; +} +/* one line for all features. Each feature, with the | in front of it, is one block, so when the row is wider + than the card the whole feature is dropped and the ellipsis never follows a lonely | */ +.htlRoomCardFeatured > span { + display: inline-block; + vertical-align: top; +} +.htlRoomCardFeatured > span + span:not(.htlRoomFeatureMore):before { + content: "|"; + margin: 0 5px; + color: #BBB; +} +.htlRoomCardFeatured i { + margin-right: 4px; + color: #777; +} +.htlRoomCardMeta { + display: flex; + align-items: center; + justify-content: space-between; + gap: 10px; + padding: 12px 0; + border-top: 1px solid #E5E5E5; + color: #555; + font-size: 15px; +} +.htlRoomCardGuests i { + margin-right: 4px; + color: #777; +} +.htlRoomCardAmen { + display: flex; + flex: 1 1 auto; + gap: 6px; + min-width: 0; + overflow: hidden; +} +.htlRoomCardAmen > span.htlRoomAmenMore { + width: auto; + min-width: 32px; + padding: 0 8px; + border-radius: 16px; + font-size: 12px; + white-space: nowrap; +} +.htlRoomCardAmen > span { + flex: 0 0 auto; + display: inline-flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + border: 1px solid #D6D6D6; + border-radius: 50%; + font-size: 14px; + color: #666; +} +.htlRoomCardFoot { + display: flex; + align-items: center; + justify-content: space-between; + border-top: 1px solid #E5E5E5; + gap: 10px; + padding-top: 14px; +} +.htlRoomCardFoot .htlRoomTypePriceText { + float: none; + margin: 0; + font-size: 22px; + font-weight: 700; + line-height: 1.2; +} +.htlRoomCardFoot .wk_roomType_price_type { + font-size: 14px; + font-weight: 400; + color: #777; +} +.htlRoomCardFoot .room_type_old_price { + display: block; + width: auto; + font-size: 14px; + font-weight: 400; +} +a.htlRoomTypeBookNow { + padding: 10px 20px; + border: 0; + border-radius: 3px; + background: #379BF0; + color: #fff; + font-weight: 700; + white-space: nowrap; +} +a.htlRoomTypeBookNow:hover { + background: #2d86d3; + color: #fff; +} +.htlRoom-owlCarousel .owl-nav .owl-prev, +.htlRoom-owlCarousel .owl-nav .owl-next { + position: absolute; + top: 38%; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + width: 44px; + height: 44px; + border-radius: 50%; + background: #fff; + box-shadow: 0 2px 8px rgba(0, 0, 0, .2); + font-size: 22px; + line-height: 1; +} +.htlRoom-owlCarousel .owl-nav .owl-prev { + left: -15px; +} +.htlRoom-owlCarousel .owl-nav .owl-next { + right: -12px; +} +.htlRoom-owlCarousel .owl-nav .disabled { + display: none; +} +@media (max-width: 767px) { + .htlRoomCardBody .htlRoomTypeNameText { + font-size: 20px; + } +} + +/* equal height cards: price row sits at the bottom, occupancy row keeps the same height with or without amenities */ +.htlRoom-owlCarousel .owl-stage { + display: flex; +} +.htlRoom-owlCarousel .owl-item { + display: flex; +} +.htlRoomCard { + display: flex; + flex-direction: column; + width: 100%; +} +.htlRoomCardBody { + display: flex; + flex: 1; + flex-direction: column; +} +.htlRoomCardFoot { + margin-top: auto; +} +.htlRoomCardGuests { + display: inline-flex; + align-items: center; + min-height: 32px; +} + +.htlRoomCard { + width: calc(100% - 4px); + margin: 2px; +} +.htlRoom-owlCarousel .owl-nav > div i { + position: relative; + left: 1px; +} + +/* no line right under the room name */ +.htlRoomTypeNameText + .htlRoomCardMeta { + border-top: 0; + padding-top: 12px; +} + +.htlRoomCardFeatured .htlRoomFeatureMore { + margin-left: 5px; +} diff --git a/modules/wkhotelroom/views/js/WkHotelRoomBlockFront.js b/modules/wkhotelroom/views/js/WkHotelRoomBlockFront.js index 216c2be8c..d921dcbac 100644 --- a/modules/wkhotelroom/views/js/WkHotelRoomBlockFront.js +++ b/modules/wkhotelroom/views/js/WkHotelRoomBlockFront.js @@ -20,7 +20,89 @@ * @license https://opensource.org/license/osl-3-0-php Open Software License version 3.0 */ +/** + * Keeps the items of a room card row (featured features, amenity icons) on one line. Items that do not fit are + * hidden whole, so a lone separator or icon is never left at the end, and a "more" marker is added at the end. + * + * @param {jQuery} $slider slider holding the room cards + * @param {Object} row + * @param {string} row.selector the row element + * @param {string} row.more class of the "more" marker + * @param {function(number): string} row.moreText text of the marker, gets the number of hidden items + * @param {boolean} [row.partial] show the first hidden item shortened with an ellipsis when enough room is left + */ +function fitRoomCardRow($slider, row) { + var MIN_PARTIAL_WIDTH = 100; // narrowest width a shortened item is shown in + + $slider.find(row.selector).each(function() { + var $row = $(this); + var $items = $row.children(':not(.' + row.more + ')').css({display: '', maxWidth: ''}); + var fits = function() { + return $row.prop('scrollWidth') <= $row.innerWidth(); + }; + + $row.children('.' + row.more).remove(); + if (fits()) { + return; + } + + // the marker takes room too, so it is added before the items are hidden + var $more = $('').appendTo($row); + var shown = $items.length; + + while (shown > 1 && !fits()) { + $items.eq(--shown).hide(); + $more.html(row.moreText($items.length - shown)); + } + + var $next = $items.eq(shown); + var $last = $items.eq(shown - 1); + var room = Math.floor($row.offset().left + $row.innerWidth() - ($last.offset().left + $last.outerWidth(true))); + + if (row.partial && $next.length && room >= MIN_PARTIAL_WIDTH) { + $more.remove(); + $next.css({display: 'inline-block', maxWidth: room - 4, overflow: 'hidden', textOverflow: 'ellipsis'}); + } + }); +} + +/** Fits the featured features and the amenity icons of every room card of the slider. */ +function fitRoomCards($slider) { + fitRoomCardRow($slider, { + selector: '.htlRoomCardFeatured', + more: 'htlRoomFeatureMore', + moreText: function() { return '…'; }, + partial: true + }); + fitRoomCardRow($slider, { + selector: '.htlRoomCardAmen', + more: 'htlRoomAmenMore', + moreText: function(hidden) { return '+' + hidden; } + }); +} + $(document).ready(function() { + $('.htlRoom-owlCarousel .owl-carousel').on('initialized.owl.carousel refreshed.owl.carousel resized.owl.carousel', function() { + fitRoomCards($(this)); + }).owlCarousel({ + loop: true, + nav: true, + navText: ['', ''], + dots: false, + autoplay: true, + autoplaySpeed: 1000, + margin: 24, + items: 1, + rtl: typeof language_is_rtl != 'undefined' && language_is_rtl, + responsive: { + 768: { items: 2 }, + 992: { items: 3 } + } + }); + // fonts and icons can change the widths after the page is shown + $(window).on('load', function() { + fitRoomCards($('.htlRoom-owlCarousel .owl-carousel')); + }); applyChangesToDescription(); $(window).on('resize', function() { resetDescriptionChanges(); diff --git a/modules/wkhotelroom/views/templates/hook/hotelRoomDisplayBlock.tpl b/modules/wkhotelroom/views/templates/hook/hotelRoomDisplayBlock.tpl index 872d29a25..b63d3bcd1 100644 --- a/modules/wkhotelroom/views/templates/hook/hotelRoomDisplayBlock.tpl +++ b/modules/wkhotelroom/views/templates/hook/hotelRoomDisplayBlock.tpl @@ -38,64 +38,72 @@ {/if} {block name='hotel_room_block_content'} -
    +
    - {assign var='htlRoomBlockIteration' value=0} - {foreach from=$hotelRoomDisplay item=roomDisplay name=htlRoom} - {if $smarty.foreach.htlRoom.iteration%2} -
    - {/if} -
    - {block name='hotel_room_block_room_type_image'} - - {$roomDisplay.name|escape:'htmlall':'UTF-8'} - +
    {/block}
    -
    +
    {/if} {/block} diff --git a/modules/wkhotelroom/wkhotelroom.php b/modules/wkhotelroom/wkhotelroom.php index c38a97d98..56abb1a23 100644 --- a/modules/wkhotelroom/wkhotelroom.php +++ b/modules/wkhotelroom/wkhotelroom.php @@ -51,6 +51,8 @@ class WkHotelRoom extends Module $dateFrom = date('Y-m-d'); $dateTo = date('Y-m-d', strtotime($dateFrom) + 86400); $useTax = HotelBookingDetail::useTax(); + $maxFeatures = (int) Configuration::get('WK_MAX_FEATURES_ROOM_SEARCH'); + $maxFeatureValues = (int) Configuration::get('WK_MAX_ROOM_TYPE_FEATURE_VALUES'); foreach ($hotelRoomDisplay as &$htlRoom) { $idProduct = $htlRoom['id_product']; $product = new Product($idProduct, false, $idLang); @@ -109,6 +111,23 @@ class WkHotelRoom extends Module 1, array(array('adults' => 1, 'children' => 0, 'child_ages' => array())) ); + $objRoomType = new HotelRoomType(); + $roomTypeInfo = $objRoomType->getRoomTypeInfoByIdProduct($idProduct); + $htlRoom['max_adults'] = $roomTypeInfo ? (int) $roomTypeInfo['max_adults'] : 0; + $htlRoom['max_children'] = $roomTypeInfo ? (int) $roomTypeInfo['max_children'] : 0; + $features = array(); + foreach (Product::getFrontFeaturesStatic($idLang, $idProduct) as $feature) { + if ($feature['is_featured'] && $feature['logo']) { + $features[$feature['id_feature']] = $features[$feature['id_feature']] ?? $feature; + $features[$feature['id_feature']]['values'][] = $feature['value']; + } + } + $htlRoom['feature'] = array_slice($features, 0, $maxFeatures ?: null); + foreach ($htlRoom['feature'] as &$roomFeature) { + $roomFeature['value'] = implode(', ', array_slice($roomFeature['values'], 0, $maxFeatureValues ?: null)); + } + unset($roomFeature); + $htlRoom['amenities'] = HotelRoomTypeAmenities::getAmenities($idProduct, $idLang, true); $htlRoom['feature_price'] = $featurePrice; $htlRoom['feature_price_diff'] = (float)($priceWithoutReduction - $featurePrice); } @@ -123,10 +142,14 @@ class WkHotelRoom extends Module 'HOTEL_ROOM_DISPLAY_DESCRIPTION', $this->context->language->id ), + 'amenity_img_dir' => _MODULE_DIR_.'hotelreservationsystem/views/img/hotel_amenities/', 'hotelRoomDisplay' => $hotelRoomDisplay ) ); + $this->context->controller->addCSS(_PS_JS_DIR_.'owl-carousel/assets/owl.carousel.min.css'); + $this->context->controller->addCSS(_PS_JS_DIR_.'owl-carousel/assets/owl.theme.default.min.css'); + $this->context->controller->addJS(_PS_JS_DIR_.'owl-carousel/owl.carousel.min.js'); $this->context->controller->addJs($this->_path.'/views/js/WkHotelRoomBlockFront.js'); $this->context->controller->addCSS($this->_path.'/views/css/WkHotelRoomBlockFront.css'); diff --git a/modules/wkroomsearchblock/views/css/wk-category-search.css b/modules/wkroomsearchblock/views/css/wk-category-search.css index 37889ddd2..b974b57c0 100644 --- a/modules/wkroomsearchblock/views/css/wk-category-search.css +++ b/modules/wkroomsearchblock/views/css/wk-category-search.css @@ -60,4 +60,54 @@ .header-rmsearch-wrapper { padding: 10px 5px;} +} + +/* searched details and the close icon are for mobile and tablet only */ +.header-rmsearch-details-wrapper, +.header-rmsearch-wrapper .close_room_serach_wrapper { + display: none;} +/* mobile and tablet: show the searched details, the search form opens with the edit button */ +@media (max-width: 991px) { + .header-rmsearch-wrapper { + display: none; + position: relative;} + .header-rmsearch-details-wrapper { + display: block;} + .header-rmsearch-wrapper .close_room_serach_wrapper { + display: block; + position: absolute; + top: 8px; + right: 15px; + z-index: 1;} + .close_room_serach_wrapper img { + width: 18px;} + .header-rmsearch-details-wrapper { + padding: 0 0 15px;} + .header-rmsearch-details-wrapper .filter_header { + font-size: 12px; + color: #333; + line-height: 25px;} + .header-rmsearch-details-wrapper .filter_header p { + margin: 0;} + .header-rmsearch-details-wrapper .search_result_info { + font-size: 15px; + font-weight: bold; + line-height: 30px; + color: #333333;} + .header-rmsearch-details-wrapper .modify_roomtype_search_btn { + border: 1px solid #777777; + font-weight: bold; + border-radius: 4px; + font-size: 13px; + padding: 6px 12px; + color: #333333; + text-align: center; + text-transform: uppercase;} + .header-rmsearch-details-wrapper .faded-txt { + color: #777777;} +} +/* desktop always shows the search form, even if it was closed on a smaller screen */ +@media (min-width: 992px) { + .header-rmsearch-wrapper { + display: block !important;} } \ No newline at end of file diff --git a/modules/wkroomsearchblock/views/css/wk-landing-page-search.css b/modules/wkroomsearchblock/views/css/wk-landing-page-search.css index 63c48a472..d4ebcab33 100644 --- a/modules/wkroomsearchblock/views/css/wk-landing-page-search.css +++ b/modules/wkroomsearchblock/views/css/wk-landing-page-search.css @@ -60,8 +60,14 @@ column-gap: 0px; } .header-rmsearch-wrapper { - height: calc(100vw - 60px); + height: auto; width: calc(100vw - 60px); + max-height: 80vh; + overflow-y: auto; + } + /* the date picker opens inside this popup, so don't clip it */ + .fancybox-inner:has(#xs_room_search_form) { + overflow: visible !important; } } .fancy_search_header_xs { diff --git a/modules/wkroomsearchblock/views/templates/hook/categoryPageSearch.tpl b/modules/wkroomsearchblock/views/templates/hook/categoryPageSearch.tpl index e0a1037a5..59cedeb92 100644 --- a/modules/wkroomsearchblock/views/templates/hook/categoryPageSearch.tpl +++ b/modules/wkroomsearchblock/views/templates/hook/categoryPageSearch.tpl @@ -22,7 +22,23 @@ {block name='category_page_search_panel'} {if isset($hotels_info) && count($hotels_info)} + {* searched information, shown on mobile and tablet only *} + {block name='category_page_search_info'} + {if isset($search_data) && $search_data} +
    +
    +

    {l s='Searched results for' mod='wkroomsearchblock'}: + +

    +
    +
    + {$search_data['htl_dtl']['hotel_name']|escape:'htmlall':'UTF-8'}, {$search_data['htl_dtl']['city']|escape:'htmlall':'UTF-8'} {if !$search_data['order_date_restrict']} {if (isset($search_data['date_from']))}{$search_data['date_from']|escape:'htmlall':'UTF-8'|date_format:"%d %b %Y"}{/if} - {if isset($search_data['date_to'])}{$search_data['date_to']|escape:'htmlall':'UTF-8'|date_format:"%d %b %Y"}{/if} ({1+$search_data['num_days']|escape:'htmlall':'UTF-8'} {l s='Days' mod='wkroomsearchblock'} {$search_data['num_days']|escape:'htmlall':'UTF-8'} {if $search_data['num_days'] > 1}{l s='Nights' mod='wkroomsearchblock'}{else}{l s='Night' mod='wkroomsearchblock'}{/if}) {/if} +
    +
    + {/if} + {/block}
    +

    {l s='Search Rooms' mod='wkroomsearchblock'}


    diff --git a/modules/wkroomsearchblock/wkroomsearchblock.php b/modules/wkroomsearchblock/wkroomsearchblock.php index ab9720af2..a0cd01280 100644 --- a/modules/wkroomsearchblock/wkroomsearchblock.php +++ b/modules/wkroomsearchblock/wkroomsearchblock.php @@ -102,9 +102,13 @@ class WkRoomSearchBlock extends Module // apply assets as per pages if ('category' == $controller) { $this->context->controller->addCSS($this->_path.'views/css/wk-category-search.css'); + $this->context->controller->addJS($this->_path.'views/js/wk-roomtype-search.js'); } if ('index' == $controller) { $this->context->controller->addCSS($this->_path.'views/css/wk-landing-page-search.css'); + // the mobile "Make Booking" modal opens via fancybox regardless of the + // unrelated PS_QUICK_VIEW setting that core normally gates it behind + $this->context->controller->addJqueryPlugin('fancybox'); } if ('product' == $controller) { $this->context->controller->addCSS($this->_path.'views/css/wk-roomtype-search.css'); diff --git a/themes/hotel-reservation-theme/css/category.css b/themes/hotel-reservation-theme/css/category.css index 712fa14ba..2d01e4fdb 100644 --- a/themes/hotel-reservation-theme/css/category.css +++ b/themes/hotel-reservation-theme/css/category.css @@ -68,6 +68,57 @@ margin-bottom: 15px; } +@media (max-width: 767px) { + .cat_cont > .col-sm-12 { + padding-left: 0; + padding-right: 0; + } + + .room_features_cont > .row { + flex-wrap: wrap; + } + + .room_features_cont > .row > [class*="col-"] { + width: 100%; + } + + .room-type-image { + width: 100%; + } + + .room_info_cont > .row:first-child { + display: flex; + flex-wrap: wrap; + align-items: baseline; + } + + .room_info_cont > .row:first-child:before, + .room_info_cont > .row:first-child:after { + display: none; + } + + .room_info_cont > .row:first-child { + justify-content: space-between; + } + + .room_info_cont .rm_heading { + font-size: 22px; + line-height: 28px; + } + + .room_info_cont .rm_left { + font-size: 14px; + } + + .room_info_cont .rm_price_val { + font-size: 26px; + } + + .room_info_cont .rm_price_txt { + font-size: 14px; + } +} + .rm_heading { color: #333333; @@ -95,7 +146,7 @@ font-weight: 400; } .room_featured_features, .room_features_cont{ - margin-top: 10px; + margin-top: 13px; } .rm_desc p { @@ -163,20 +214,38 @@ p.capa_txt { .rm_amen { - color: #555555; - width: 18px; - display: inline-block; - margin-right: 10px; + box-sizing: border-box; + display: inline-flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + margin-right: 6px; margin-bottom: 5px; - font-size: 16px; + border: 1px solid #D6D6D6; + border-radius: 50%; + font-size: 14px; color: #555555; } +img.rm_amen +{ + padding: 7px; + object-fit: contain; +} +.room_featured_features { + display: flex; + flex-wrap: wrap; + gap: 6px 8px; +} .room_featured_feature { - display: inline-block; - margin: 0 10px 10px 0; + display: inline-flex; + align-items: center; + gap: 6px; + margin: 0; color: #555; + white-space: nowrap; } .room_featured_feature i{ @@ -308,6 +377,23 @@ p.capa_txt { margin-bottom: 0; } } +@media (max-width: 991px) { + .room_features_cont > div { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 8px 0; + margin-bottom: 10px; + } + .booking_room_fields { + display: flex; + flex-wrap: wrap; + gap: 10px; + } + .booking_room_fields .form-group:not(.occupancy_count_block) { + width: 100%; + } +} @media (min-width: 1200px) { .booking_guest_occupancy_conatiner .form-group { margin-bottom: 0; @@ -359,4 +445,318 @@ p.capa_txt { .rm_desc .view_more { display: inline-block; -} \ No newline at end of file +} + +.layered_filter_cont:has(#filter_price_silder) { + padding-bottom: 15px; + margin-bottom: 20px; +} + +@media (min-width: 768px) and (max-width: 991px) { + #category #left_column, + #category #center_column { + width: 100%; + } + + .catSortBlock .col-sm-3 { + width: auto; + } + + .catSortBlock .filter_dw_cont .btn { + white-space: nowrap; + } + + .catSortBlock .filter_dw_cont .sort_btn_span { + margin-right: 8px; + } +} + +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md .capa_txt { + padding-left: 0; + } +} + +.rm_amen_more { + display: none; +} +@media (max-width: 1199px) { + .rm_amen_extra { + display: none; + } + + .rm_amen_more { + display: inline-block; + margin-bottom: 5px; + padding: 0 8px; + border: 1px solid #379BF0; + border-radius: 16px; + font-size: 12px; + line-height: 30px; + color: #379BF0; + vertical-align: top; + } +} + +@media (max-width: 567px) { + .booking_room_fields > div, + .booking_room_fields .booking_guest_occupancy_conatiner, + .booking_room_fields .booking_guest_occupancy_conatiner > .form-group, + .booking_room_fields .booking_guest_occupancy_conatiner .booking_guest_occupancy, + .booking_room_fields .btn_book_now_with_occupancy { + width: 100%; + } +} + +@media (min-width: 568px) and (max-width: 767px) { + .booking_room_fields > div { + width: calc(50% - 5px); + } + .booking_room_fields .booking_guest_occupancy_conatiner > .form-group, + .booking_room_fields .booking_guest_occupancy_conatiner .booking_guest_occupancy, + .booking_room_fields .btn_book_now_with_occupancy { + width: 100%; + } +} + +@media (max-width: 767px) { + .booking_room_fields .btn_book_now_with_occupancy { + text-align: center; + } +} + +/* mobile filters: bottom Sort / Filter bar, sort sheet and full screen filters panel */ +.mf_header, .mf_footer, .mf_nav, .mf_bar, .mf_sheet { + display: none; +} +@media (max-width: 993px) { + body.category { + padding-bottom: 64px; + } + .catSortBlock { + display: none; + } + #category_data_cont .room_cont:first-child { + border-top: 0; + padding-top: 0; + } + .mf_bar { + display: flex; + position: fixed; + left: 0; + right: 0; + bottom: 0; + z-index: 90; + background: #fff; + border-top: 1px solid #E5E5E5; + box-shadow: 0 -2px 8px rgba(0, 0, 0, .08); + } + .mf_bar button { + flex: 1; + padding: 16px 8px; + border: 0; + background: none; + font-size: 16px; + font-weight: 700; + color: #333; + } + .mf_bar button i { + margin-right: 4px; + color: #379BF0; + } + .mf_bar button b { + display: inline-block; + min-width: 20px; + padding: 0 5px; + border-radius: 10px; + background: #379BF0; + font-size: 12px; + line-height: 20px; + color: #fff; + } + .mf_bar button b:empty { + display: none; + } + .mf_bar button + button { + border-left: 1px solid #E5E5E5; + } + .mf_sheet { + position: fixed; + inset: 0; + z-index: 9000; + background: rgba(0, 0, 0, .45); + align-items: flex-end; + } + .mf_sheet.mf_open { + display: flex; + } + .mf_sheet_box { + width: 100%; + max-height: 80vh; + overflow-y: auto; + background: #fff; + border-radius: 16px 16px 0 0; + } + .mf_sheet_head { + display: flex; + align-items: center; + justify-content: space-between; + padding: 16px; + border-bottom: 1px solid #E5E5E5; + font-size: 14px; + font-weight: 700; + letter-spacing: .5px; + text-transform: uppercase; + color: #777; + } + .mf_sheet_head button { + border: 0; + background: none; + font-size: 28px; + line-height: 1; + color: #333; + } + .mf_sheet ul { + margin: 0; + padding: 0; + list-style: none; + } + .mf_sheet li:after { + content: ""; + float: right; + width: 22px; + height: 22px; + border: 2px solid #777; + border-radius: 50%; + } + .mf_sheet li.mf_selected:after { + border-color: #379BF0; + box-shadow: inset 0 0 0 4px #fff, inset 0 0 0 12px #379BF0; + } + .mf_sheet li { + padding: 16px; + font-size: 16px; + color: #333; + } + #filter_results { + display: none; + margin: 0; + } + body.mf_filter_open { + overflow: hidden; + } + body.mf_filter_open #filter_results { + display: flex; + flex-direction: column; + position: fixed; + inset: 0; + z-index: 9000; + background: #fff; + } + #filter_results .mf_header { + display: flex; + align-items: center; + gap: 12px; + padding: 14px 16px; + border-bottom: 1px solid #E5E5E5; + } + #filter_results .mf_header .mf_back { + padding: 0 4px; + border: 0; + background: none; + font-size: 24px; + line-height: 1; + transform: translateY(-5px); + } + #filter_results .mf_title { + flex: 1; + font-size: 18px; + } + #filter_results .mf_clear_all { + border: 0; + background: none; + font-size: 14px; + color: #999; + text-decoration: underline; + } + #filter_results > .col-sm-12 { + flex: 1; + display: flex; + padding: 0; + min-height: 0; + } + #filter_results .mf_nav { + display: block; + flex: 0 0 38%; + overflow-y: auto; + background: #F5F5F5; + } + #filter_results .mf_tab { + display: block; + width: 100%; + padding: 16px; + border: 0; + border-left: 3px solid transparent; + background: none; + text-align: left; + font-size: 15px; + color: #333; + } + #filter_results .mf_tab b { + float: right; + font-size: 13px; + color: #379BF0; + } + #filter_results .mf_tab.mf_active { + background: #fff; + border-left-color: #379BF0; + } + #filter_results .layered_filter_cont { + display: none; + flex: 1; + margin: 0; + border: 0; + overflow-y: auto; + padding: 8px 4px; + } + #filter_results .layered_filter_cont.mf_active { + display: block; + } + #filter_results .layered_filter_cont .clear_filter { + display: none; + } + #filter_results .lf_sub_cont { + max-height: none; + overflow: visible; + padding: 0 16px 10px 12px; + } + #filter_results .mf_footer { + display: block; + padding: 12px 16px; + border-top: 1px solid #E5E5E5; + background: #fff; + } + #filter_results .mf_footer .mf_apply span { + font-size: 14px; + padding: 11px; + font-weight: 600; + color: #FFFFFF; + text-transform: uppercase; + text-align: center; + } + #filter_results .mf_footer .mf_apply { + background-color: #1292FF; + box-shadow: 0 0px 20px 0 rgba(0, 0, 0, 0.34); + border-radius: 2px; + padding: 0px 50px; + } +} +@media (max-width: 467px) { + #filter_results .mf_footer .mf_apply { + float: none !important; + display: block; + width: 100%; + padding: 0; + text-align: center; + } +} diff --git a/themes/hotel-reservation-theme/css/daterangepicker.css b/themes/hotel-reservation-theme/css/daterangepicker.css index 4d4e8cea9..1f39d04b3 100644 --- a/themes/hotel-reservation-theme/css/daterangepicker.css +++ b/themes/hotel-reservation-theme/css/daterangepicker.css @@ -89,3 +89,15 @@ .date-picker-wrapper .first-date-selected, .date-picker-wrapper .last-date-selected { background-color: #1292ff !important; } +@media (max-width: 400px) { + .date-picker-wrapper { + max-width: calc(100vw - 20px); + } + .date-picker-wrapper .month-wrapper table tr td .day { + width: 28px; + padding: 8px 6px; + } + .date-picker-wrapper .month-wrapper table .week-name { + height: 32px; + } +} diff --git a/themes/hotel-reservation-theme/css/global.css b/themes/hotel-reservation-theme/css/global.css index f114321c7..d70e202d5 100644 --- a/themes/hotel-reservation-theme/css/global.css +++ b/themes/hotel-reservation-theme/css/global.css @@ -235,7 +235,8 @@ table { html { font-size: 62.5%; - -webkit-tap-highlight-color: transparent; } + -webkit-tap-highlight-color: transparent; + overflow-x: hidden; } body { @@ -243,7 +244,8 @@ body { font-size: 13px; line-height: 1.42857; color: #777777; - background-color: #fff; } + background-color: #fff; + overflow-x: hidden; } input, button, @@ -5974,6 +5976,12 @@ textarea { #columns { padding: 0; } +@media (max-width: 767px) { + #columns { + padding-left: 15px; + padding-right: 15px; + } +} #columns:has(#center_column > *) { position: relative; padding-bottom: 50px; @@ -7553,6 +7561,9 @@ div.star a:hover { .ie8 .breadcrumb .navigation-pipe { width: 20px; } +.copyRightWrapper { + text-align: center; } + .footer-container { background-color: #333333; padding-top: 30px; } @@ -8243,6 +8254,20 @@ p.p.payment_module { p.cheque-indent { margin-bottom: 9px; } +@media (max-width: 767px) { + .cheque-box .form-group > .col-xs-4 { + width: 100%; } } + +@media (max-width: 480px) { + .cheque-box + .cart_navigation .button-exclusive { + display: block; + margin-bottom: 15px; } + .cheque-box + .cart_navigation .button-medium { + float: none; + display: block; + width: 100%; + text-align: center; } } + @media (max-width: 480px) { p.payment_module a { background-position: 12px 8px!important; @@ -8920,11 +8945,18 @@ body .ui-tooltip { .payment_option_logo { height: 50px; - max-height: 50px; } + max-height: 50px; + max-width: 100%; } .payment_module_adv { height: 120px; - max-height: 120px; } + max-height: 120px; + max-width: 100%; } + +@media (max-width: 480px) { + .payment_module_adv { + height: 80px; + max-height: 80px; } } .payment_option_selected { display: none; @@ -9025,6 +9057,29 @@ body .ui-tooltip { font-weight: 400; line-height: 23px; } +@media (max-width: 767px) { + .home_block_heading { + font-size: 28px; + line-height: 32px; + margin-bottom: 15px; } + .home_block_description { + font-size: 15px; + line-height: 20px; } + .home_block_desc_wrapper { + padding: 0 15px; + margin-bottom: 30px; + } + .home_block_container{ + padding-top: 30px; + padding-bottom: 30px; + } + #hotelAmenitiesBlock{ + padding-bottom: 1px; + } + .margin-btm-50 { + margin-bottom: 0px; + } +} .home_block_desc_line { border-color: #333333; width: 100px; @@ -9391,6 +9446,12 @@ div a.our_properties_link{ font-size: 17px; font-weight: 400;} +/* the menu panel already has a link to the properties page on mobile */ +@media (max-width: 767px) { + div a.our_properties_link { + display: none; } +} + .ui-tooltip-trigger { cursor: pointer; display: inline-block; diff --git a/themes/hotel-reservation-theme/css/modules/blockcart/blockcart.css b/themes/hotel-reservation-theme/css/modules/blockcart/blockcart.css index 4ed382348..1a38645c9 100644 --- a/themes/hotel-reservation-theme/css/modules/blockcart/blockcart.css +++ b/themes/hotel-reservation-theme/css/modules/blockcart/blockcart.css @@ -185,6 +185,18 @@ @media (max-width: 355px) { #header .cart_block { width: 270px; } } +@media (max-width: 480px) { + /* anchor the dropdown to the full-width header column so it stays inside the viewport */ + #header .header-top-item:has(> .shopping_cart) { + position: static; } + #header .shopping_cart > a:first-child { + position: relative; + overflow: visible; } + #header .cart_block { + top: 70px; + right: 15px; + width: calc(100vw - 30px); + max-width: 355px; } } /* @media (max-width: 1200px) { #header .cart_block { width: 100%; } }*/ @@ -317,6 +329,9 @@ float: none; margin-right: 0; margin-bottom: 10px; } } + @media (max-width: 480px) { + #layer_cart .layer_cart_product { + padding: 15px; } } #layer_cart .layer_cart_product .layer_cart_product_info { padding: 38px 0 0 0; } #layer_cart .layer_cart_product .layer_cart_product_info #layer_cart_product_title { @@ -334,6 +349,9 @@ -webkit-border-radius: 0px; border-radius: 0px 4px 4px 0px; position: relative; } + @media (max-width: 480px) { + #layer_cart .layer_cart_cart { + padding: 15px 15px 150px 15px; } } @media (min-width: 1200px) { #layer_cart .layer_cart_cart { min-height: 318px; } } @@ -357,13 +375,17 @@ #layer_cart .layer_cart_cart h2 { font-size: 18px; } } #layer_cart .layer_cart_cart .layer_cart_row { - padding: 0 0 7px 0; } + padding: 0 0 7px 0; + overflow: hidden; } #layer_cart .layer_cart_cart .button-container { position: absolute; bottom: 0; left: 0; width: 100%; padding: 0px 30px 20px 30px; } + @media (max-width: 480px) { + #layer_cart .layer_cart_cart .button-container { + padding: 0px 15px 20px 15px; } } #layer_cart .layer_cart_cart .button-container .btn { margin-bottom: 10px; } #layer_cart .layer_cart_cart .button-container a.button.button-medium { @@ -378,6 +400,28 @@ #layer_cart .layer_cart_cart .button-container span.exclusive-medium i { padding-right: 5px; color: #777777; } + @media (max-width: 575px) { + #layer_cart .layer_cart_product .product-image-container { + float: none; + margin-right: 0; + margin-bottom: 10px; } + #layer_cart { + left: 0; + width: 92%; + margin-left: 4%; + margin-right: 4%; } + #layer_cart .layer_cart_product .layer_cart_product_info { + padding-top: 5px; } + #layer_cart .layer_cart_cart .button-container .btn { + display: block; + width: 100%; + margin-right: 0; + text-align: center; } + #layer_cart .layer_cart_cart .button-container span.exclusive-medium { + margin-right: 0; } } + @media (min-width: 576px) and (max-width: 991px) { + #layer_cart .layer_cart_cart .button-container { + text-align: center; } } #layer_cart .cross { position: absolute; right: 7px; diff --git a/themes/hotel-reservation-theme/css/modules/blocknewsletter/blocknewsletter.css b/themes/hotel-reservation-theme/css/modules/blocknewsletter/blocknewsletter.css index 46b2e74c1..e194ac1ca 100644 --- a/themes/hotel-reservation-theme/css/modules/blocknewsletter/blocknewsletter.css +++ b/themes/hotel-reservation-theme/css/modules/blocknewsletter/blocknewsletter.css @@ -178,6 +178,10 @@ position: relative; padding: 0px 20px; } +.button.button-medium.newsletter-btn:hover, .button.button-medium.newsletter-btn:focus { + background: #0f7fe0; + background-image: none; +} #newsletter-input { background-color: #3a3a3a; diff --git a/themes/hotel-reservation-theme/css/occupancy.css b/themes/hotel-reservation-theme/css/occupancy.css index aebf0494e..8105bcdf3 100644 --- a/themes/hotel-reservation-theme/css/occupancy.css +++ b/themes/hotel-reservation-theme/css/occupancy.css @@ -128,9 +128,16 @@ width: 100%;} - @media (max-width: 450) { + @media (max-width: 450px) { .booking_occupancy_wrapper .occupancy_info_block .occupancy_count_block { width: 100%;} .booking_occupancy_wrapper .occupancy_info_block .occupancy_count { width: 80%;} + /* room list and product page booking form: keep adults and children side by side, same as desktop */ + .booking_guest_occupancy_conatiner .booking_occupancy_wrapper .occupancy_info_block .occupancy_count_block, + .booking-form .booking_occupancy_wrapper .occupancy_info_block .occupancy_count_block { + width: 50%;} + .booking_guest_occupancy_conatiner .booking_occupancy_wrapper .occupancy_info_block .occupancy_count, + .booking-form .booking_occupancy_wrapper .occupancy_info_block .occupancy_count { + width: auto;} } \ No newline at end of file diff --git a/themes/hotel-reservation-theme/css/order-confirmation.css b/themes/hotel-reservation-theme/css/order-confirmation.css index 9ea9c3785..d24f7e8cb 100644 --- a/themes/hotel-reservation-theme/css/order-confirmation.css +++ b/themes/hotel-reservation-theme/css/order-confirmation.css @@ -30,6 +30,12 @@ margin-bottom: 0; } +@media (max-width: 767px) { + .fancybox-wrap.fancybox-extra-services .card { + width: calc(100vw - 40px); + } +} + .fancybox-wrap.fancybox-extra-services .fancybox-close { background: none; top: 12px; @@ -254,6 +260,12 @@ margin: 0; } +@media (max-width: 768px) { + .table.table-summary { + margin-bottom: 0; + border: none; + } +} .table.table-summary.table-sm td { padding: 8px 0; } diff --git a/themes/hotel-reservation-theme/css/order-detail.css b/themes/hotel-reservation-theme/css/order-detail.css index 1a39b7e47..c3797ffa8 100644 --- a/themes/hotel-reservation-theme/css/order-detail.css +++ b/themes/hotel-reservation-theme/css/order-detail.css @@ -288,22 +288,48 @@ } @media (max-width: 576px) { + .hotel-details .card-header, .refund_element_details .card-header { flex-direction: column; align-items: flex-start; } + .hotel-details .card-header .booking-actions-wrap, .refund_element_details .card-header .booking-actions-wrap { margin-top: 10px; margin-left: -10px; } + .hotel-details .card-header .booking-actions-wrap { + margin-left: -6px; + } + + .hotel-details .card-header .booking-actions-wrap .btn { + margin-left: 6px; + padding-left: 10px; + padding-right: 10px; + font-size: 13px; + } + .product-detail .num-refunded-rooms { display: block; float: none; } } +@media (max-width: 360px) { + .hotel-details .card-header .booking-actions-wrap { + margin-left: -5px; + } + + .hotel-details .card-header .booking-actions-wrap .btn { + margin-left: 5px; + padding-left: 8px; + padding-right: 8px; + font-size: 12px; + } +} + @media (min-width: 768px) and (max-width: 1200px) { .refund_element_details .card-header .booking-actions-wrap .col-xs-12, .service-product-details .card-header .booking-actions-wrap .col-xs-12 { flex-wrap: nowrap; diff --git a/themes/hotel-reservation-theme/css/order-opc.css b/themes/hotel-reservation-theme/css/order-opc.css index f3f8fb381..e39e4ac1e 100644 --- a/themes/hotel-reservation-theme/css/order-opc.css +++ b/themes/hotel-reservation-theme/css/order-opc.css @@ -575,6 +575,52 @@ width: 50%; } } +@media (max-width: 991px) { + #order-opc .cart_voucher_detail_block span.cart_discount_name { + width: 50%; + } +} +/* Mobile & tablet: show cart total + voucher blocks before the payment block */ +@media (max-width: 991px) { + #order-opc #content > .row { + display: flex; + flex-direction: column; + } + #order-opc #content > .row:before, + #order-opc #content > .row:after { + display: none; + } + #order-opc #content > .row > .col-md-8, + #order-opc #content > .row > .col-md-8 > #oprder-opc-accordion { + display: contents; + } + #order-opc #content > .row > .col-md-8 > #oprder-opc-accordion > .card { + order: 0; + margin-left: 15px; + margin-right: 15px; + } + #order-opc #content > .row > .col-md-4 { + order: 1; + width: 100%; + } + #order-opc #content > .row > .col-md-8 > #oprder-opc-accordion > #order-payment-block { + order: 2; + } +} +@media (max-width: 480px) { + #order-opc .proceed_btn_block .button-medium, + #order-opc .proceed_btn_block .btn-edit-guest-info, + #order-opc #login_form_content #SubmitLogin { + float: none !important; + display: block; + width: 100%; + padding: 0 20px; + margin-right: 0; + margin-bottom: 10px; + text-align: center; + box-sizing: border-box; + } +} @media (max-width: 480px) { #order-opc .cart_voucher_detail_block span.cart_discount_name { width: 50%; diff --git a/themes/hotel-reservation-theme/css/product.css b/themes/hotel-reservation-theme/css/product.css index ae9d789e8..74f06c6a7 100644 --- a/themes/hotel-reservation-theme/css/product.css +++ b/themes/hotel-reservation-theme/css/product.css @@ -1336,12 +1336,12 @@ Quick View Styles @media (min-width: 768px) and (max-width: 1199px) { .num_avail_rooms_alert { float: left!important;} - .booking_room_fields .form-group { + .booking_room_fields .form-group:not(.occupancy_count_block) { width: 100%;}} @media (max-width: 450px) { .num_avail_rooms_alert { float: left!important;} - .booking_room_fields .form-group { + .booking_room_fields .form-group:not(.occupancy_count_block) { width: 100%;}} /* booking form loading */ @@ -1621,6 +1621,28 @@ ul.service-product-nav > li:hover { .service-product-element .service-product-actions { display: flex; + margin-left: auto; +} +@media (max-width: 575px) { + .service-product-element .service-product-actions { + width: 100%; + margin-top: 8px; + flex-wrap: wrap; + justify-content: flex-end; + row-gap: 8px; + } + .service-product-element .service-product-actions .qty_container { + flex: 0 0 auto; + } +} +@media (max-width: 370px) { + .service-product-element .service-product-actions .qty_container { + margin-right: 4px; + } + .service-product-element .service-product-actions .qty_container .qty_count { + padding-left: 10px; + padding-right: 10px; + } } .service-product-element .qty_container > * { @@ -1805,3 +1827,32 @@ ul.service-product-nav > li:hover { display: block; } } + +/* mobile and tablet: show the booking form right after the images, before the service products */ +@media (max-width: 991px) { + .primary_block { + display: flex; + flex-direction: column; + } + .primary_block:before, + .primary_block:after { + display: none; + } + .primary_block .pb-left-column, + .primary_block .pb-right-column { + display: contents; + } + + .primary_block .booking-form { + margin-bottom: 20px; + } + /* the column wrappers are gone, so give the sections their side gutter back */ + .primary_block .room_type_img_containter, + .primary_block .booking-form, + .primary_block #service_products_cont, + .primary_block .product_info_containter { + margin-left: 15px; + margin-right: 15px; + } + +} diff --git a/themes/hotel-reservation-theme/order-opc.tpl b/themes/hotel-reservation-theme/order-opc.tpl index 5cbb76425..a7c42de50 100644 --- a/themes/hotel-reservation-theme/order-opc.tpl +++ b/themes/hotel-reservation-theme/order-opc.tpl @@ -227,7 +227,7 @@ {include file="$tpl_dir./order-carrier.tpl"}
    *} -
    +
    {block name='order_opc_payment_heading'}