страна
All checks were successful
Deploy hotel / deploy-kdo (push) Successful in 59s

This commit is contained in:
2026-07-26 16:24:20 +05:00
parent d539e1f0c0
commit f0da3d2b3f
4 changed files with 47 additions and 29 deletions

View File

@@ -49,7 +49,7 @@ function createReview(req, res) {
const { author_name, country_code, country_name, city, stars, text, review_code } = req.body;
const ip = req.ip || req.connection.remoteAddress || 'unknown';
if (!author_name || !country_code || stars === undefined || !text || !review_code) {
if (!author_name || stars === undefined || !text || !review_code) {
return res.status(400).json({ error: 'Missing required fields' });
}

View File

@@ -28,6 +28,8 @@ const translations = {
// Review Form
'form.select_country': 'Выберите страну',
'form.select_city': 'Город (необязательно)',
'form.another_country': 'Другая страна',
'form.country_placeholder': 'Введите название страны',
'form.another_city': 'Другой город',
'form.city_placeholder': 'Введите название города',
'form.rating': 'Оценка',
@@ -355,6 +357,8 @@ const translations = {
// Review Form
'form.select_country': 'Select country',
'form.select_city': 'City (optional)',
'form.another_country': 'Other country',
'form.country_placeholder': 'Enter country name',
'form.another_city': 'Other city',
'form.city_placeholder': 'Enter city name',
'form.rating': 'Rating',
@@ -682,6 +686,8 @@ const translations = {
// Review Form
'form.select_country': 'Атәыла алхразы',
'form.select_city': 'Ақалақь (иахәҭахым)',
'form.another_country': 'Атәыла даҽаны',
'form.country_placeholder': 'Атәыла ахьӡ аҭазыргыла',
'form.another_city': 'Ақалақь даҽаны',
'form.city_placeholder': 'Ақалақь ахьӡ аҭазыргыла',
'form.rating': 'Ахә',

View File

@@ -941,6 +941,12 @@
</div>
<div class="review-error" id="countryError" data-i18n="validation.country_required">Выберите страну</div>
</div>
<div class="review-form-group" id="otherCountryGroup" style="display: none;">
<label data-i18n="form.another_country">Другая страна</label>
<input type="text" class="review-form-control" id="reviewOtherCountry" data-i18n-placeholder="form.country_placeholder" placeholder="Введите название страны">
</div>
<div class="review-form-group">
<label data-i18n="form.select_city">Город (необязательно)</label>
<div class="review-select-wrapper" id="citySelectWrapper">
@@ -984,12 +990,7 @@
<div class="review-form-group">
<label data-i18n="form.hotel_code">Код гостиницы <span class="required">*</span></label>
<div class="review-code-wrapper">
<input type="password" class="review-form-control" id="reviewCode" required data-i18n-placeholder="form.code_placeholder" placeholder="Получите на ресепшене">
<button type="button" class="toggle-code" onclick="toggleCodeVisibility()">
<i class="fas fa-eye"></i>
</button>
</div>
<input type="text" class="review-form-control" id="reviewCode" required data-i18n-placeholder="form.code_placeholder" placeholder="Получите на ресепшене">
<small class="hint" data-i18n="form.code_hint">Код сообщается гостям на ресепшене отеля</small>
<div class="review-error" id="codeError" data-i18n="validation.code_invalid">Неверный код гостиницы</div>
</div>

View File

@@ -181,6 +181,11 @@ function populateCountrySelect() {
otherGroup.appendChild(opt);
});
select.appendChild(otherGroup);
const otherCountryOpt = document.createElement('option');
otherCountryOpt.value = '__other__';
otherCountryOpt.textContent = I18n.t('form.another_country');
select.appendChild(otherCountryOpt);
}
let currentCountryCode = null;
@@ -194,6 +199,19 @@ function setupCountryChangeHandler() {
const citySelect = document.getElementById('reviewCity');
const cityWrapper = document.getElementById('citySelectWrapper');
const otherCityGroup = document.getElementById('otherCityGroup');
const otherCountryGroup = document.getElementById('otherCountryGroup');
if (countryCode === '__other__') {
otherCountryGroup.style.display = 'block';
document.getElementById('reviewOtherCountry').focus();
citySelect.innerHTML = '<option value="">' + I18n.t('form.select_city') + '</option>';
citySelect.disabled = true;
cityWrapper.style.display = 'block';
otherCityGroup.style.display = 'none';
return;
}
otherCountryGroup.style.display = 'none';
if (!countryCode) {
citySelect.innerHTML = '<option value="">' + I18n.t('form.select_city') + '</option>';
@@ -292,28 +310,14 @@ function initStarsSlider() {
updateStars(slider.value);
}
function toggleCodeVisibility() {
const input = document.getElementById('reviewCode');
const btn = document.querySelector('.toggle-code i');
if (input.type === 'password') {
input.type = 'text';
btn.className = 'fas fa-eye-slash';
} else {
input.type = 'password';
btn.className = 'fas fa-eye';
}
}
function resetReviewForm() {
const form = document.getElementById('reviewForm');
const countryEl = document.getElementById('reviewCountry');
const cityEl = document.getElementById('reviewCity');
const cityWrapper = document.getElementById('citySelectWrapper');
const otherCityGroup = document.getElementById('otherCityGroup');
const otherCountryGroup = document.getElementById('otherCountryGroup');
const starsSlider = document.getElementById('starsSlider');
const codeInput = document.getElementById('reviewCode');
const toggleBtn = document.querySelector('.toggle-code i');
const modalBody = document.getElementById('reviewModalBody');
if (form) form.reset();
@@ -321,9 +325,8 @@ function resetReviewForm() {
if (cityEl) cityEl.innerHTML = '<option value="">' + I18n.t('form.select_city') + '</option>';
if (cityWrapper) cityWrapper.style.display = 'block';
if (otherCityGroup) otherCityGroup.style.display = 'none';
if (otherCountryGroup) otherCountryGroup.style.display = 'none';
if (starsSlider) starsSlider.value = 5;
if (codeInput) codeInput.type = 'password';
if (toggleBtn) toggleBtn.className = 'fas fa-eye';
if (form) {
form.querySelectorAll('.review-error').forEach(el => el.classList.remove('show'));
@@ -340,6 +343,8 @@ function resetReviewForm() {
initStarsSlider();
setupReviewFormSubmit();
setupCountryChangeHandler();
setupCityChangeHandler();
}
function getReviewCity() {
@@ -353,6 +358,9 @@ function getReviewCity() {
function getReviewCountry() {
const select = document.getElementById('reviewCountry');
if (!select) return '';
if (select.value === '__other__') {
return document.getElementById('reviewOtherCountry').value.trim() || '';
}
const selectedOption = select.options[select.selectedIndex];
return selectedOption ? selectedOption.textContent : '';
}
@@ -366,11 +374,14 @@ function validateReviewForm() {
form.querySelectorAll('.review-error').forEach(el => el.classList.remove('show'));
form.querySelectorAll('.review-form-control').forEach(el => el.classList.remove('error'));
const country = document.getElementById('reviewCountry').value;
if (!country) {
document.getElementById('reviewCountry').classList.add('error');
document.getElementById('countryError').classList.add('show');
isValid = false;
const countryVal = document.getElementById('reviewCountry').value;
if (countryVal === '__other__') {
const otherCountry = document.getElementById('reviewOtherCountry').value.trim();
if (!otherCountry) {
document.getElementById('reviewOtherCountry').classList.add('error');
document.getElementById('countryError').classList.add('show');
isValid = false;
}
}
const city = getReviewCity();