Initial commit: Korea Tourism Agency website with AdminJS

- Full-stack Node.js/Express application with PostgreSQL
- Modern ES modules architecture
- AdminJS admin panel with Sequelize ORM
- Tourism routes, guides, articles, bookings management
- Responsive Bootstrap 5 frontend
- Docker containerization with docker-compose
- Complete database schema with migrations
- Authentication system for admin panel
- Dynamic placeholder images for tour categories
This commit is contained in:
2025-11-29 18:13:17 +09:00
commit 409e6c146b
53 changed files with 16195 additions and 0 deletions

108
views/guides/index.ejs Normal file
View File

@@ -0,0 +1,108 @@
<!-- Hero Section -->
<section class="hero-section bg-primary text-white text-center py-5">
<div class="container">
<div class="row">
<div class="col-lg-8 mx-auto">
<h1 class="display-4 fw-bold mb-4">Наши гиды</h1>
<p class="lead">Профессиональные и опытные гиды сделают ваше путешествие незабываемым</p>
</div>
</div>
</div>
</section>
<!-- Guides Grid -->
<section class="py-5">
<div class="container">
<% if (guides.length === 0) { %>
<div class="text-center py-5">
<i class="fas fa-user-tie text-muted" style="font-size: 4rem;"></i>
<h3 class="mt-3 text-muted">Гиды не найдены</h3>
<p class="text-muted">В данный момент нет доступных гидов.</p>
</div>
<% } else { %>
<div class="row">
<% guides.forEach(guide => { %>
<div class="col-lg-4 col-md-6 mb-4">
<div class="card h-100 shadow-sm">
<% if (guide.image_url && guide.image_url.trim()) { %>
<img src="<%= guide.image_url %>" class="card-img-top" alt="<%= guide.name %>" style="height: 250px; object-fit: cover;">
<% } else { %>
<img src="/images/placeholder.jpg" class="card-img-top" alt="<%= guide.name %>" style="height: 250px; object-fit: cover;">
<% } %>
<div class="card-body d-flex flex-column">
<h5 class="card-title"><%= guide.name %></h5>
<div class="mb-3">
<% if (guide.specialization === 'city') { %>
<span class="badge bg-info">
<i class="fas fa-city me-1"></i>Городские туры
</span>
<% } else if (guide.specialization === 'mountain') { %>
<span class="badge bg-success">
<i class="fas fa-mountain me-1"></i>Горные походы
</span>
<% } else if (guide.specialization === 'fishing') { %>
<span class="badge bg-primary">
<i class="fas fa-fish me-1"></i>Рыбалка
</span>
<% } %>
</div>
<% if (guide.bio) { %>
<p class="card-text text-muted flex-grow-1"><%= truncateText(guide.bio, 120) %></p>
<% } %>
<div class="mt-auto">
<% if (guide.languages) { %>
<div class="mb-2">
<small class="text-muted">
<i class="fas fa-language me-1"></i>
<%= guide.languages %>
</small>
</div>
<% } %>
<% if (guide.avg_rating) { %>
<div class="mb-2">
<%- generateStars(guide.avg_rating) %>
<small class="text-muted ms-2">(<%= parseFloat(guide.avg_rating).toFixed(1) %>)</small>
</div>
<% } %>
<div class="d-flex justify-content-between align-items-center mb-3">
<div>
<small class="text-muted">
<i class="fas fa-calendar me-1"></i><%= guide.experience %> лет опыта
</small>
</div>
<div>
<small class="text-muted">
<i class="fas fa-route me-1"></i><%= guide.route_count || 0 %> туров
</small>
</div>
</div>
<a href="/guides/<%= guide.id %>" class="btn btn-primary w-100">
<i class="fas fa-user me-1"></i>Подробнее
</a>
</div>
</div>
</div>
</div>
<% }); %>
</div>
<% } %>
</div>
</section>
<!-- CTA Section -->
<section class="bg-light py-5">
<div class="container text-center">
<h2 class="mb-4">Нужен индивидуальный подход?</h2>
<p class="lead text-muted mb-4">Наши гиды готовы создать уникальный маршрут специально для вас!</p>
<a href="/contact" class="btn btn-primary btn-lg">
<i class="fas fa-envelope me-1"></i>Связаться с нами
</a>
</div>
</section>