Files
tourrism_site/views/routes/detail.ejs
Andrey K. Choi 409e6c146b 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
2025-11-29 18:13:17 +09:00

289 lines
13 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- Hero Section -->
<section class="hero-section bg-primary text-white">
<div class="container py-5">
<div class="row align-items-center">
<div class="col-lg-8">
<h1 class="display-4 fw-bold mb-3"><%= route.title %></h1>
<p class="lead mb-4"><%= route.description %></p>
<div class="d-flex flex-wrap gap-2 mb-4">
<% if (route.type === 'city') { %>
<span class="badge bg-info fs-6">
<i class="fas fa-city me-1"></i>Городской тур
</span>
<% } else if (route.type === 'mountain') { %>
<span class="badge bg-success fs-6">
<i class="fas fa-mountain me-1"></i>Горный поход
</span>
<% } else if (route.type === 'fishing') { %>
<span class="badge bg-info fs-6">
<i class="fas fa-fish me-1"></i>Рыбалка
</span>
<% } %>
<span class="badge <%= route.difficulty_level === 'easy' ? 'bg-success' : route.difficulty_level === 'moderate' ? 'bg-warning' : 'bg-danger' %> fs-6">
<%= route.difficulty_level === 'easy' ? 'Легко' : route.difficulty_level === 'moderate' ? 'Средне' : 'Сложно' %>
</span>
</div>
</div>
<div class="col-lg-4">
<div class="bg-white text-dark p-4 rounded shadow">
<h4 class="text-primary mb-3">Детали тура</h4>
<div class="mb-3">
<strong class="d-block">Цена</strong>
<span class="h4 text-primary">₩<%= formatCurrency(route.price) %></span>
</div>
<div class="mb-3">
<strong class="d-block">Продолжительность</strong>
<span><%= route.duration %> дней</span>
</div>
<div class="mb-3">
<strong class="d-block">Максимум участников</strong>
<span><%= route.max_group_size %> человек</span>
</div>
<a href="/contact" class="btn btn-primary w-100">
<i class="fas fa-calendar-plus me-1"></i>Забронировать
</a>
</div>
</div>
</div>
</div>
</section>
<div class="container py-5">
<div class="row">
<div class="col-lg-8">
<!-- Route Image -->
<%
let placeholderImage = '/images/placeholder.jpg';
if (route.type === 'city') {
placeholderImage = '/images/city-tour-placeholder.webp';
} else if (route.type === 'mountain') {
placeholderImage = '/images/mountain-placeholder.jpg';
} else if (route.type === 'fishing') {
placeholderImage = '/images/fish-placeholder.jpg';
}
%>
<% if (route.image_url && route.image_url.trim()) { %>
<img src="<%= route.image_url %>" class="img-fluid rounded mb-4" alt="<%= route.title %>">
<% } else { %>
<img src="<%= placeholderImage %>" class="img-fluid rounded mb-4" alt="<%= route.title %>">
<% } %>
<!-- Route Content -->
<div class="mb-5">
<h2 class="mb-3">Описание маршрута</h2>
<div class="content">
<%= route.content || 'Подробное описание маршрута будет доступно в ближайшее время.' %>
</div>
</div>
<!-- Included Services -->
<% if (route.included_services && route.included_services.length > 0) { %>
<div class="mb-5">
<h3 class="mb-3">Что включено</h3>
<div class="row">
<% route.included_services.forEach(service => { %>
<div class="col-md-6 mb-2">
<i class="fas fa-check text-success me-2"></i><%= service %>
</div>
<% }); %>
</div>
</div>
<% } %>
<!-- Reviews Section -->
<div class="mb-5">
<h3 class="mb-4">Отзывы (<%= reviews.length %>)</h3>
<!-- Review Form -->
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">Оставить отзыв</h5>
</div>
<div class="card-body">
<form id="reviewForm">
<input type="hidden" name="route_id" value="<%= route.id %>">
<% if (route.guide_id) { %>
<input type="hidden" name="guide_id" value="<%= route.guide_id %>">
<% } %>
<div class="row">
<div class="col-md-6 mb-3">
<label for="customer_name" class="form-label">Ваше имя *</label>
<input type="text" class="form-control" id="customer_name" name="customer_name" required>
</div>
<div class="col-md-6 mb-3">
<label for="customer_email" class="form-label">Email</label>
<input type="email" class="form-control" id="customer_email" name="customer_email">
</div>
</div>
<div class="mb-3">
<label for="rating" class="form-label">Оценка *</label>
<div class="star-rating">
<input type="radio" id="star5" name="rating" value="5">
<label for="star5" title="Отлично"><i class="fas fa-star"></i></label>
<input type="radio" id="star4" name="rating" value="4">
<label for="star4" title="Хорошо"><i class="fas fa-star"></i></label>
<input type="radio" id="star3" name="rating" value="3">
<label for="star3" title="Нормально"><i class="fas fa-star"></i></label>
<input type="radio" id="star2" name="rating" value="2">
<label for="star2" title="Плохо"><i class="fas fa-star"></i></label>
<input type="radio" id="star1" name="rating" value="1">
<label for="star1" title="Очень плохо"><i class="fas fa-star"></i></label>
</div>
</div>
<div class="mb-3">
<label for="comment" class="form-label">Комментарий *</label>
<textarea class="form-control" id="comment" name="comment" rows="4"
placeholder="Поделитесь впечатлениями о туре..." required></textarea>
</div>
<button type="submit" class="btn btn-primary">
<i class="fas fa-paper-plane me-1"></i>Отправить отзыв
</button>
</form>
</div>
</div>
<!-- Reviews List -->
<% if (reviews.length === 0) { %>
<p class="text-muted">Пока нет отзывов об этом туре. Будьте первым!</p>
<% } else { %>
<% reviews.forEach(review => { %>
<div class="card mb-3">
<div class="card-body">
<div class="d-flex justify-content-between align-items-start mb-2">
<h6 class="mb-0"><%= review.customer_name %></h6>
<div>
<%- generateStars(review.rating) %>
</div>
</div>
<p class="card-text"><%= review.comment %></p>
<small class="text-muted"><%= formatDate(review.created_at) %></small>
</div>
</div>
<% }); %>
<% } %>
</div>
</div>
<!-- Sidebar -->
<div class="col-lg-4">
<!-- Guide Info -->
<% if (route.guide_name) { %>
<div class="card mb-4">
<div class="card-body">
<h5 class="card-title">Ваш гид</h5>
<% if (route.guide_image) { %>
<img src="<%= route.guide_image %>" class="rounded-circle mb-3" width="80" height="80" style="object-fit: cover;" alt="<%= route.guide_name %>">
<% } %>
<h6><%= route.guide_name %></h6>
<% if (route.guide_bio) { %>
<p class="text-muted small"><%= route.guide_bio %></p>
<% } %>
</div>
</div>
<% } %>
<!-- Contact Card -->
<div class="card">
<div class="card-body">
<h5 class="card-title">Нужна помощь?</h5>
<p class="card-text">Свяжитесь с нами для получения дополнительной информации о туре.</p>
<div class="mb-3">
<strong class="d-block">Телефон</strong>
<span>+7 (495) 123-45-67</span>
</div>
<div class="mb-3">
<strong class="d-block">Email</strong>
<span>info@koreatour.ru</span>
</div>
<a href="/contact" class="btn btn-outline-primary w-100">
<i class="fas fa-envelope me-1"></i>Написать нам
</a>
</div>
</div>
</div>
</div>
</div>
<!-- Similar Tours -->
<section class="bg-light py-5">
<div class="container">
<h2 class="text-center mb-5">Похожие туры</h2>
<div class="text-center">
<a href="/routes?type=<%= route.type %>" class="btn btn-primary">
Посмотреть все туры категории
</a>
</div>
</div>
</section>
<style>
.star-rating {
display: flex;
flex-direction: row-reverse;
justify-content: flex-end;
}
.star-rating input {
display: none;
}
.star-rating label {
color: #ddd;
font-size: 1.5rem;
margin: 0 2px;
cursor: pointer;
transition: color 0.2s;
}
.star-rating input:checked ~ label,
.star-rating label:hover,
.star-rating label:hover ~ label {
color: #ffc107;
}
</style>
<script>
// Review form submission
document.getElementById('reviewForm').addEventListener('submit', async function(e) {
e.preventDefault();
const formData = new FormData(this);
const data = Object.fromEntries(formData);
// Validate rating
if (!data.rating) {
alert('Пожалуйста, выберите оценку');
return;
}
try {
const response = await fetch('/api/reviews', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
const result = await response.json();
if (result.success) {
alert(result.message);
this.reset();
// Optionally reload the page to show new review
// location.reload();
} else {
alert(result.message);
}
} catch (error) {
console.error('Error submitting review:', error);
alert('Произошла ошибка при отправке отзыва');
}
});
</script>