номер

This commit is contained in:
2026-05-11 01:48:56 +05:00
parent 33a10fbc6e
commit fc63252327
6 changed files with 172 additions and 56 deletions

View File

@@ -1,7 +1,8 @@
const ROOM_TYPES = {
economy: { id: 'Эконом', name: 'Эконом', pricePerGuest: 2500 },
standard: { id: 'Стандарт', name: 'Стандарт', pricePerGuest: 4000 },
vip: { id: 'VIP Люкс', name: 'VIP Люкс', pricePerGuest: 8000 }
economy: { id: '2x-местный', name: '2x-местный', pricePerGuest: 1500 },
standard: { id: '3х-местный', name: '3х-местный', pricePerGuest: 2000 },
family: { id: 'Семейный', name: 'Семейный', pricePerGuest: 3000 },
vip: { id: 'Люкс', name: 'Люкс', pricePerGuest: 4500 }
};
const BOOKING_STATUSES = {
@@ -14,14 +15,16 @@ const BOOKING_STATUSES = {
};
const DEFAULT_ROOMS = [
{ type: ROOM_TYPES.economy.id, name: 'Эконом 1', description: 'Бюджетный номер', rooms_count: 3, single_beds: 2, double_beds: 0, has_sofa: 0, has_ac: 0, has_wifi: 1, has_shower: 1, max_guests: 2, price_per_guest: ROOM_TYPES.economy.pricePerGuest },
{ type: ROOM_TYPES.standard.id, name: 'Стандарт 1', description: 'Комфортный номер', rooms_count: 2, single_beds: 0, double_beds: 1, has_sofa: 1, has_ac: 1, has_wifi: 1, has_shower: 1, max_guests: 3, price_per_guest: ROOM_TYPES.standard.pricePerGuest },
{ type: ROOM_TYPES.vip.id, name: 'VIP Люкс 1', description: 'Премиум номер', rooms_count: 1, single_beds: 0, double_beds: 1, has_sofa: 1, has_ac: 1, has_wifi: 1, has_shower: 1, max_guests: 4, price_per_guest: ROOM_TYPES.vip.pricePerGuest }
{ type: ROOM_TYPES.economy.id, name: '2x-местный 1', description: 'Номер на двоих', rooms_count: 15, single_beds: 0, double_beds: 1, has_sofa: 0, has_ac: 1, has_wifi: 1, has_shower: 1, max_guests: 2, price_per_guest: ROOM_TYPES.economy.pricePerGuest },
{ type: ROOM_TYPES.standard.id, name: '3х-местный 1', description: 'Номер на троих', rooms_count: 8, single_beds: 0, double_beds: 1, has_sofa: 0, has_ac: 1, has_wifi: 1, has_shower: 1, max_guests: 3, price_per_guest: ROOM_TYPES.standard.pricePerGuest },
{ type: ROOM_TYPES.family.id, name: 'Семейный 1', description: 'Семейный номер', rooms_count: 4, single_beds: 0, double_beds: 2, has_sofa: 0, has_ac: 1, has_wifi: 1, has_shower: 1, max_guests: 4, price_per_guest: ROOM_TYPES.family.pricePerGuest },
{ type: ROOM_TYPES.vip.id, name: 'Люкс 1', description: 'Люкс', rooms_count: 3, single_beds: 0, double_beds: 1, has_sofa: 1, has_ac: 1, has_wifi: 1, has_shower: 1, max_guests: 4, price_per_guest: ROOM_TYPES.vip.pricePerGuest }
];
const ROOM_PRICES = {
[ROOM_TYPES.economy.id]: ROOM_TYPES.economy.pricePerGuest,
[ROOM_TYPES.standard.id]: ROOM_TYPES.standard.pricePerGuest,
[ROOM_TYPES.family.id]: ROOM_TYPES.family.pricePerGuest,
[ROOM_TYPES.vip.id]: ROOM_TYPES.vip.pricePerGuest
};
@@ -35,9 +38,10 @@ const STATUS_LIST = [
];
const ROOM_TYPE_LIST = [
ROOM_TYPES.economy.id,
ROOM_TYPES.standard.id,
ROOM_TYPES.vip.id
'2x-местный',
'3х-местный',
'Семейный',
'Люкс'
];
function getRoomPrice(roomType) {

View File

@@ -58,6 +58,7 @@ function validatePromocode(promocode, callback) {
}
function getBookingsForAdmin(req, res) {
const page = parseInt(req.query.page) || 1;
const limit = parseInt(req.query.limit) || 20;
const offset = (page - 1) * limit;
const search = req.query.search || '';

View File

@@ -771,7 +771,7 @@ function renderBookings() {
});
const statuses = ['новая', 'оплачена', 'зарезервирована', 'заселена', 'выехала', 'отменена'];
const rooms = ['Эконом', 'Стандарт', 'VIP Люкс'];
const rooms = ['2x-местный', '3х-местный', 'Семейный', 'Люкс'];
const tbody = document.getElementById('allBookings');
if (rows.length === 0) {

View File

@@ -532,7 +532,31 @@ h1, h2, h3, h4 {
display: flex;
flex-wrap: wrap;
gap: clamp(6px, 1.5vw, 10px);
margin-bottom: clamp(15px, 3vw, 20px);
margin-bottom: clamp(10px, 2vw, 15px);
}
.room-meta {
display: flex;
flex-wrap: wrap;
gap: 12px;
margin-bottom: clamp(10px, 2vw, 15px);
font-size: 0.8rem;
color: #888;
}
.room-meta span {
display: flex;
align-items: center;
gap: 5px;
}
.room-meta i {
color: var(--primary);
}
.room-extra {
font-size: 0.75rem;
color: #e67e22;
margin-bottom: 15px;
padding: 6px 10px;
background: #fef3e2;
border-radius: 6px;
}
.room-feature-tag {
display: inline-flex;

View File

@@ -160,84 +160,141 @@
<div class="section-badge">Размещение</div>
<h2 class="section-title">Выберите свой номер</h2>
<div class="abkhazian-pattern"></div>
<p class="section-subtitle">Три категории номеров — от экономного до VIP-комфорта. Каждый номер оснащён всем необходимым для идеального отдыха.</p>
<p class="section-subtitle">Четыре категории номеров — от 2x-местного до люкса. Каждый номер оснащён всем необходимым для идеального отдыха.</p>
</div>
<div class="row g-4">
<!-- Economy -->
<!-- 2x-местный -->
<div class="col-lg-4 animate-on-scroll">
<div class="room-card">
<div class="room-image">
<img src="img/1faae356b-9f79-489d-8165-c37a47b82040.webp" alt="Эконом номер">
<div class="room-category">Эконом</div>
<img src="img/1faae356b-9f79-489d-8165-c37a47b82040.webp" alt="2x-местный номер">
<div class="room-category">Стандарт</div>
</div>
<div class="room-body">
<h3 class="room-name">Эконом</h3>
<p class="room-desc">Уютный номер с одной кроватью — идеально для соло-путешественника или экономного отдыха. Чистый, светлый и со всем необходимым.</p>
<h3 class="room-name">2x-местный</h3>
<p class="room-desc">Уютный номер на двоих с одной или двумя кроватями. Идеально для пары или друзей. Кондиционер, TV, холодильник, Wi-Fi.</p>
<div class="room-meta">
<span><i class="fas fa-door-open"></i> 20 м²</span>
<span><i class="fas fa-layer-group"></i> Этажи 1-3</span>
<span><i class="fas fa-shower"></i> Душ в номере</span>
</div>
<div class="room-features">
<span class="room-feature-tag"><i class="fas fa-bed"></i> 1 кровать</span>
<span class="room-feature-tag"><i class="fas fa-bed"></i> 2 кровати</span>
<span class="room-feature-tag"><i class="fas fa-snowflake"></i> Кондиционер</span>
<span class="room-feature-tag"><i class="fas fa-tv"></i> ТВ</span>
<span class="room-feature-tag"><i class="fas fa-wifi"></i> WiFi</span>
<span class="room-feature-tag"><i class="fas fa-shower"></i> Душ</span>
<span class="room-feature-tag"><i class="fas fa-sink"></i> Холодильник</span>
<span class="room-feature-tag"><i class="fas fa-mug-hot"></i> Чайник</span>
</div>
<div class="room-footer">
<div class="room-price">
<span class="amount">от 1 500 ₽</span>
<span class="period"> / ночь</span>
</div>
<button class="btn-book" data-bs-toggle="modal" data-bs-target="#bookingModal" data-room="Эконом">Забронировать</button>
<button class="btn-book" data-bs-toggle="modal" data-bs-target="#bookingModal" data-room="2x-местный">Забронировать</button>
</div>
</div>
</div>
</div>
<!-- Standard -->
<div class="col-lg-4 animate-on-scroll">
<div class="room-card featured">
<div class="room-image">
<img src="img/1006bc9be-64c6-43e3-9625-1a862d04930c.webp" alt="Стандарт номер">
<div class="room-category">Стандарт</div>
</div>
<div class="room-body">
<h3 class="room-name">Стандарт</h3>
<p class="room-desc">Просторный номер с двумя односпальными или одной двухспальной кроватью. Отличный выбор для пары или небольшой семьи.</p>
<div class="room-features">
<span class="room-feature-tag"><i class="fas fa-bed"></i> 2 кровати / 1 двухспальная</span>
<span class="room-feature-tag"><i class="fas fa-snowflake"></i> Кондиционер</span>
<span class="room-feature-tag"><i class="fas fa-wifi"></i> WiFi</span>
<span class="room-feature-tag"><i class="fas fa-shower"></i> Душ</span>
</div>
<div class="room-footer">
<div class="room-price">
<span class="amount">от 2 500 ₽</span>
<span class="period"> / ночь</span>
</div>
<button class="btn-book" data-bs-toggle="modal" data-bs-target="#bookingModal" data-room="Стандарт">Забронировать</button>
</div>
</div>
</div>
</div>
<!-- VIP -->
<!-- 3х-местный -->
<div class="col-lg-4 animate-on-scroll">
<div class="room-card">
<div class="room-image">
<img src="img/1eae46658-cfca-4b65-82f0-e5868af5541b.webp" alt="VIP номер">
<div class="room-category">VIP</div>
<img src="img/1006bc9be-64c6-43e3-9625-1a862d04930c.webp" alt="3х-местный номер">
<div class="room-category">Стандарт</div>
</div>
<div class="room-body">
<h3 class="room-name">VIP Люкс</h3>
<p class="room-desc">Две комнаты: спальня с двухспальной кроватью и гостиная с удобным диваном. Премиум-комфорт для тех, кто ценит простор и роскошь.</p>
<h3 class="room-name">3х-местный</h3>
<p class="room-desc">Комфортный трёхместный номер с односпальными или двуспальной кроватью. Просторный и светлый с видом на море.</p>
<div class="room-meta">
<span><i class="fas fa-door-open"></i> 20 м²</span>
<span><i class="fas fa-layer-group"></i> Этажи 1-3</span>
<span><i class="fas fa-shower"></i> Душ в номере</span>
</div>
<div class="room-features">
<span class="room-feature-tag"><i class="fas fa-bed"></i> 2 комнаты</span>
<span class="room-feature-tag"><i class="fas fa-couch"></i> Двухспальная + диван</span>
<span class="room-feature-tag"><i class="fas fa-bed"></i> 3 кровати</span>
<span class="room-feature-tag"><i class="fas fa-snowflake"></i> Кондиционер</span>
<span class="room-feature-tag"><i class="fas fa-tv"></i> ТВ</span>
<span class="room-feature-tag"><i class="fas fa-wifi"></i> WiFi</span>
<span class="room-feature-tag"><i class="fas fa-shower"></i> Душ</span>
<span class="room-feature-tag"><i class="fas fa-sink"></i> Холодильник</span>
<span class="room-feature-tag"><i class="fas fa-mug-hot"></i> Чайник</span>
<span class="room-feature-tag"><i class="fas fa-sea"></i> Вид на море</span>
</div>
<div class="room-footer">
<div class="room-price">
<span class="amount">от 2 000 ₽</span>
<span class="period"> / ночь</span>
</div>
<button class="btn-book" data-bs-toggle="modal" data-bs-target="#bookingModal" data-room="3х-местный">Забронировать</button>
</div>
</div>
</div>
</div>
<!-- Семейный -->
<div class="col-lg-4 animate-on-scroll">
<div class="room-card featured">
<div class="room-image">
<img src="img/1eae46658-cfca-4b65-82f0-e5868af5541b.webp" alt="Семейный номер">
<div class="room-category">Семейный</div>
</div>
<div class="room-body">
<h3 class="room-name">Семейный</h3>
<p class="room-desc">Просторный двухкомнатный номер для семьи до 4 человек. Две спальни с двуспальными кроватями. Возможны дополнительные места.</p>
<div class="room-meta">
<span><i class="fas fa-door-open"></i> 40 м²</span>
<span><i class="fas fa-layer-group"></i> Этаж 2</span>
<span><i class="fas fa-shower"></i> Душ в номере</span>
</div>
<div class="room-features">
<span class="room-feature-tag"><i class="fas fa-bed"></i> 4 кровати</span>
<span class="room-feature-tag"><i class="fas fa-door-open"></i> 2 комнаты</span>
<span class="room-feature-tag"><i class="fas fa-snowflake"></i> Кондиционер</span>
<span class="room-feature-tag"><i class="fas fa-tv"></i> ТВ</span>
<span class="room-feature-tag"><i class="fas fa-wifi"></i> WiFi</span>
<span class="room-feature-tag"><i class="fas fa-sink"></i> Холодильник</span>
<span class="room-feature-tag"><i class="fas fa-mug-hot"></i> Чайник</span>
</div>
<div class="room-footer">
<div class="room-price">
<span class="amount">от 3 000 ₽</span>
<span class="period"> / ночь</span>
</div>
<button class="btn-book" data-bs-toggle="modal" data-bs-target="#bookingModal" data-room="Семейный">Забронировать</button>
</div>
</div>
</div>
</div>
<!-- Люкс -->
<div class="col-lg-4 animate-on-scroll">
<div class="room-card">
<div class="room-image">
<img src="img/1eae46658-cfca-4b65-82f0-e5868af5541b.webp" alt="Люкс">
<div class="room-category">Люкс</div>
</div>
<div class="room-body">
<h3 class="room-name">Люкс</h3>
<p class="room-desc">Элегантный двухкомнатный люкс с двуспальной кроватью, гостиной зоной и великолепным видом на море. Премиум-комфорт.</p>
<div class="room-meta">
<span><i class="fas fa-door-open"></i> 50 м²</span>
<span><i class="fas fa-layer-group"></i> Этаж 2</span>
<span><i class="fas fa-shower"></i> Душ в номере</span>
</div>
<div class="room-features">
<span class="room-feature-tag"><i class="fas fa-bed"></i> 4 кровати</span>
<span class="room-feature-tag"><i class="fas fa-door-open"></i> 2 комнаты</span>
<span class="room-feature-tag"><i class="fas fa-snowflake"></i> Кондиционер</span>
<span class="room-feature-tag"><i class="fas fa-tv"></i> ТВ</span>
<span class="room-feature-tag"><i class="fas fa-wifi"></i> WiFi</span>
<span class="room-feature-tag"><i class="fas fa-sink"></i> Холодильник</span>
<span class="room-feature-tag"><i class="fas fa-mug-hot"></i> Чайник</span>
<span class="room-feature-tag"><i class="fas fa-sea"></i> Вид на море</span>
</div>
<div class="room-footer">
<div class="room-price">
<span class="amount">от 4 500 ₽</span>
<span class="period"> / ночь</span>
</div>
<button class="btn-book" data-bs-toggle="modal" data-bs-target="#bookingModal" data-room="VIP Люкс">Забронировать</button>
<button class="btn-book" data-bs-toggle="modal" data-bs-target="#bookingModal" data-room="Люкс">Забронировать</button>
</div>
</div>
</div>

View File

@@ -71,12 +71,42 @@ document.querySelectorAll('.btn-book').forEach(btn => {
btn.addEventListener('click', function() {
const room = this.getAttribute('data-room');
document.getElementById('selectedRoom').value = room;
updateGuestOptions(room);
hidePriceInfo();
});
});
function updateGuestOptions(room) {
const guestsSelect = document.querySelector('[name="guests"]');
if (!guestsSelect) return;
const options2x = [
{ value: 1, text: '1 гость' },
{ value: 2, text: '2 гостя' }
];
const options3x = [
{ value: 1, text: '1 гость' },
{ value: 2, text: '2 гостя' },
{ value: 3, text: '3 гостя' }
];
const optionsDefault = [
{ value: 1, text: '1 гость' },
{ value: 2, text: '2 гостя' },
{ value: 3, text: '3 гостя' },
{ value: 4, text: '4 гостя' }
];
let options = optionsDefault;
if (room === '2x-местный') options = options2x;
else if (room === '3х-местный') options = options3x;
guestsSelect.innerHTML = options.map(o => `<option value="${o.value}">${o.text}</option>`).join('');
}
// Price calculation
const ROOM_PRICES = { 'Эконом': 2500, 'Стандарт': 4000, 'VIP Люкс': 8000 };
const ROOM_PRICES = { '2x-местный': 1500, '3х-местный': 2000, 'Семейный': 3000, 'Люкс': 4500 };
let currentPromocodeData = null;
function calculateNights(checkin, checkout) {