diff --git a/modules/translations/index.js b/modules/translations/index.js
index 7aca60d..81af4a7 100644
--- a/modules/translations/index.js
+++ b/modules/translations/index.js
@@ -26,7 +26,7 @@ const translations = {
'select.alphabetical': 'По алфавиту',
// Review Form
- 'form.select_country': 'Выберите страну',
+ 'form.select_country': 'Выберите страну (необязательно)',
'form.select_city': 'Город (необязательно)',
'form.another_country': 'Другая страна',
'form.country_placeholder': 'Введите название страны',
@@ -355,7 +355,7 @@ const translations = {
'select.alphabetical': 'Alphabetical',
// Review Form
- 'form.select_country': 'Select country',
+ 'form.select_country': 'Select country (optional)',
'form.select_city': 'City (optional)',
'form.another_country': 'Other country',
'form.country_placeholder': 'Enter country name',
@@ -684,7 +684,7 @@ const translations = {
'select.alphabetical': 'Алфавит ала',
// Review Form
- 'form.select_country': 'Атәыла алхразы',
+ 'form.select_country': 'Атәыла алхразы (иахәҭахым)',
'form.select_city': 'Ақалақь (иахәҭахым)',
'form.another_country': 'Атәыла даҽаны',
'form.country_placeholder': 'Атәыла ахьӡ аҭазыргыла',
diff --git a/public/data/countries.js b/public/data/countries.js
index df9a784..b120837 100644
--- a/public/data/countries.js
+++ b/public/data/countries.js
@@ -1,5 +1,6 @@
const COUNTRIES = [
{ code: 'AF', name: 'Afghanistan', nameRu: 'Афганистан' },
+ { code: 'AB', name: 'Abkhazia', nameRu: 'Абхазия' },
{ code: 'AL', name: 'Albania', nameRu: 'Албания' },
{ code: 'DZ', name: 'Algeria', nameRu: 'Алжир' },
{ code: 'AD', name: 'Andorra', nameRu: 'Андорра' },
diff --git a/public/index.html b/public/index.html
index 700576f..ba5a7ba 100644
--- a/public/index.html
+++ b/public/index.html
@@ -80,14 +80,14 @@
-
0%
+
0%
довольных гостей
@@ -936,7 +936,7 @@
Выберите страну
diff --git a/public/js/main.js b/public/js/main.js
index aff9b3d..f101479 100644
--- a/public/js/main.js
+++ b/public/js/main.js
@@ -37,9 +37,22 @@ document.querySelectorAll('.animate-on-scroll').forEach(el => {
});
// Counter animation
-const counterObserver = new IntersectionObserver((entries) => {
+const statsPromise = fetch('/api/stats').then(r => r.ok ? r.json() : null).catch(() => null);
+
+const counterObserver = new IntersectionObserver(async (entries) => {
+ const stats = await statsPromise;
+
entries.forEach(entry => {
if (entry.isIntersecting) {
+ if (stats) {
+ entry.target.querySelectorAll('.counter[data-stat]').forEach(el => {
+ const stat = el.getAttribute('data-stat');
+ if (stats[stat] !== undefined) {
+ el.setAttribute('data-target', stats[stat]);
+ }
+ });
+ }
+
const counters = entry.target.querySelectorAll('.counter');
counters.forEach(counter => {
const target = parseInt(counter.getAttribute('data-target'));
diff --git a/public/js/reviews.js b/public/js/reviews.js
index d8caafa..776088d 100644
--- a/public/js/reviews.js
+++ b/public/js/reviews.js
@@ -140,13 +140,24 @@ function populateCountrySelect() {
const select = document.getElementById('reviewCountry');
if (!select) return;
+ const PINNED_CODES = ['RU', 'AB'];
+
select.innerHTML = '';
+ const pinnedCountries = countriesCache.filter(c => PINNED_CODES.includes(c.code));
+ pinnedCountries.forEach(country => {
+ const opt = document.createElement('option');
+ opt.value = country.code;
+ opt.textContent = I18n.currentLang === 'ru' ? country.nameRu : country.name;
+ select.appendChild(opt);
+ });
+
const popularCodes = popularCountriesCache.map(c => c.country_code);
const popularCountries = [];
const otherCountries = [];
countriesCache.forEach(country => {
+ if (PINNED_CODES.includes(country.code)) return;
if (popularCodes.includes(country.code)) {
popularCountries.push(country);
} else {
diff --git a/server.js b/server.js
index 0f6ff4e..30b9114 100644
--- a/server.js
+++ b/server.js
@@ -392,6 +392,28 @@ app.get('/api/translations/:lang', (req, res) => {
res.json(translations);
});
+app.get('/api/stats', (req, res) => {
+ db.get(`SELECT COUNT(DISTINCT type) as count FROM rooms WHERE is_active = 1`, [], (err, row) => {
+ if (err) {
+ console.error('Stats categories error:', err);
+ return res.status(500).json({ error: 'Database error' });
+ }
+ const categories = (row && row.count > 0) ? row.count : Object.keys(config.ROOM_TYPES).length;
+
+ db.get(`SELECT COUNT(*) as total, SUM(CASE WHEN stars >= 4 THEN 1 ELSE 0 END) as satisfied FROM reviews WHERE is_approved = 1`, [], (err2, row2) => {
+ if (err2) {
+ console.error('Stats reviews error:', err2);
+ return res.status(500).json({ error: 'Database error' });
+ }
+ let satisfaction = 100;
+ if (row2 && row2.total > 0) {
+ satisfaction = Math.round((row2.satisfied / row2.total) * 100);
+ }
+ res.json({ categories, satisfaction });
+ });
+ });
+});
+
app.get('/api/countries-cities', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'data', 'countries-cities.js'));
});
@@ -404,6 +426,7 @@ app.get('/api/countries', (req, res) => {
if (match) {
try {
let jsonStr = match[1];
+ jsonStr = jsonStr.replace(/(\{|\,)\s*(\w+):/g, '$1"$2":');
jsonStr = jsonStr.replace(/'/g, '"');
const countries = JSON.parse(jsonStr);
res.json(countries);