Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,69 @@ <h2 id="reservationModalTitle" class="modal-title" data-i18n="reservation.title"
</div>
</div>

<!-- Reviews Modal -->
<section id="reviews" class="reviews-modal" aria-hidden="true" role="dialog" aria-labelledby="reviewsModalTitle">
<div class="reviews-modal-content">
<button id="closeReviewsModal" class="reviews-modal-close" aria-label="Close modal">&times;</button>
<div class="reviews-modal-header">
<span class="section-label" data-i18n="reviews.label">Guest Experiences</span>
<h2 id="reviewsModalTitle" class="modal-title" data-i18n="reviews.title">Customer Reviews</h2>
</div>

<!-- Review cards rendered dynamically by JS -->
<div id="reviews-grid" class="reviews-grid"></div>

<!-- Review submission form -->
<div class="review-form-wrapper">
<h3 class="review-form-heading" data-i18n="reviews.share">Share Your Experience</h3>

<form id="review-form" novalidate>
<div class="form-group">
<label for="review-name" data-i18n="reviews.name">Your Name</label>
<input
type="text"
id="review-name"
name="name"
data-i18n-placeholder="reviews.name_placeholder"
placeholder="e.g. Priya Sharma"
autocomplete="name"
required
/>
</div>

<div class="form-group">
<fieldset id="star-input">
<legend data-i18n="reviews.rating">Rating</legend>
<div class="star-input" role="group" aria-label="Star rating">
<button type="button" class="star-btn" data-value="1" aria-label="1 star">★</button>
<button type="button" class="star-btn" data-value="2" aria-label="2 stars">★</button>
<button type="button" class="star-btn" data-value="3" aria-label="3 stars">★</button>
<button type="button" class="star-btn" data-value="4" aria-label="4 stars">★</button>
<button type="button" class="star-btn" data-value="5" aria-label="5 stars">★</button>
</div>
<input type="hidden" id="review-rating" name="rating" value="0" />
</fieldset>
</div>

<div class="form-group">
<label for="review-text" data-i18n="reviews.text">Your Review</label>
<textarea
id="review-text"
name="text"
rows="4"
data-i18n-placeholder="reviews.text_placeholder"
placeholder="Tell us about your visit..."
required
></textarea>
</div>

<button type="submit" class="btn btn-primary" data-i18n="reviews.submit">Submit Review</button>
<div id="review-msg" class="form-note" style="display: none;"></div>
</form>
</div>
</div>
</section>

<button id="backToTop" data-i18n="back_to_top">BACK TO TOP ▲</button>

<script src="script.js" defer></script>
Expand Down
57 changes: 57 additions & 0 deletions script.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,12 @@ function smoothScroll(e) {
closeMobileMenu();
return;
}
if (targetId === '#reviews') {
e.preventDefault();
openReviewsModal();
closeMobileMenu();
return;
}
if (!targetId || targetId.startsWith('http') || targetId === '#') return;
const target = document.querySelector(targetId);
if (!target) return;
Expand Down Expand Up @@ -1047,6 +1053,10 @@ function setupReviews() {
setTimeout(() => {
reviewMsg.style.display = "none";
}, 3000);

if (typeof closeReviewsModal === "function") {
setTimeout(closeReviewsModal, 1500);
}
});
}

Expand Down Expand Up @@ -2082,6 +2092,52 @@ function setupReservationModal() {
}
}

function openReviewsModal() {
const modal = document.getElementById("reviews");
if (!modal) return;
modal.classList.add("active");
modal.setAttribute("aria-hidden", "false");
document.body.style.overflow = "hidden";
}

function closeReviewsModal() {
const modal = document.getElementById("reviews");
if (!modal) return;
modal.classList.remove("active");
modal.setAttribute("aria-hidden", "true");
document.body.style.overflow = "";
}

function setupReviewsModal() {
const modal = document.getElementById("reviews");
const closeBtn = document.getElementById("closeReviewsModal");

if (closeBtn) {
closeBtn.addEventListener("click", closeReviewsModal);
}

if (modal) {
modal.addEventListener("click", (e) => {
if (e.target === modal) closeReviewsModal();
});
}

document.addEventListener("keydown", (e) => {
if (e.key === "Escape" && modal && modal.classList.contains("active")) {
closeReviewsModal();
}
});

// Bind clicks on navbar/footer reviews link to open modal
document.querySelectorAll('a[href="#reviews"]').forEach((link) => {
link.addEventListener("click", (e) => {
e.preventDefault();
openReviewsModal();
if (typeof closeMobileMenu === "function") closeMobileMenu();
});
});
}

// =============================================
// Feature 9: Reservation Success & Calendar Integration
// =============================================
Expand Down Expand Up @@ -2416,6 +2472,7 @@ document.addEventListener('DOMContentLoaded', () => {
if (navToggle) navToggle.addEventListener("click", toggleMobileMenu);
if (reservationForm) reservationForm.addEventListener("submit", handleFormSubmit);
setupReservationModal();
setupReviewsModal();

window.addEventListener("scroll", handleScroll, { passive: true });
window.addEventListener("resize", () => {
Expand Down
193 changes: 193 additions & 0 deletions style.css
Original file line number Diff line number Diff line change
Expand Up @@ -4558,3 +4558,196 @@ body.light-theme .newsletter-form input {
}
}

/* ── Reviews Modal Overlay ── */
.reviews-modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 3500;
background-color: rgba(16, 13, 11, 0.85);
backdrop-filter: blur(8px);
justify-content: center;
align-items: center;
padding: 20px;
overflow-y: auto;
}

.reviews-modal.active {
display: flex;
}

.reviews-modal-content {
background-color: var(--color-bg-card, #2a2725);
border: 1px solid var(--color-border, #3d3835);
border-radius: 16px;
width: 100%;
max-width: 680px;
padding: 32px;
position: relative;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.6);
animation: modalReveal 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.15);
max-height: 90vh;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 20px;
}

/* Scrollable reviews grid in modal */
.reviews-modal .reviews-grid {
display: grid;
grid-template-columns: 1fr;
gap: 16px;
margin-bottom: 8px;
max-height: 250px;
overflow-y: auto;
padding-right: 8px;
}

.reviews-modal .review-card {
min-height: auto;
padding: 18px;
gap: 10px;
}

/* Custom scrollbar for reviews grid in modal */
.reviews-modal .reviews-grid::-webkit-scrollbar {
width: 6px;
}
.reviews-modal .reviews-grid::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.05);
border-radius: 3px;
}
.reviews-modal .reviews-grid::-webkit-scrollbar-thumb {
background: var(--color-border, #3d3835);
border-radius: 3px;
}
.reviews-modal .reviews-grid::-webkit-scrollbar-thumb:hover {
background: var(--color-primary, #d4af37);
}

.reviews-modal-close {
position: absolute;
top: 18px;
right: 22px;
background: transparent;
border: none;
font-size: 2rem;
color: var(--color-text-muted, #a0958d);
cursor: pointer;
line-height: 1;
transition: color 0.2s ease, transform 0.2s ease;
}

.reviews-modal-close:hover {
color: var(--color-primary, #d4af37);
transform: scale(1.1);
}

.reviews-modal-header {
margin-bottom: 12px;
text-align: center;
}

.reviews-modal-header .modal-title {
font-family: var(--font-serif);
font-size: 2rem;
color: var(--color-text, #f5f0eb);
margin: 6px 0;
}

.reviews-modal-header .modal-subtitle {
font-size: 0.9rem;
color: var(--color-text-muted, #a0958d);
}

.reviews-modal .review-form-wrapper {
border-top: 1px solid var(--color-border, #3d3835);
padding-top: 24px;
}

.reviews-modal .review-form-heading {
font-family: var(--font-serif);
font-size: 1.5rem;
text-align: center;
margin-bottom: 20px;
color: var(--color-text, #f5f0eb);
}

.reviews-modal form {
display: flex;
flex-direction: column;
gap: 16px;
}

.reviews-modal .form-group {
display: flex;
flex-direction: column;
gap: 6px;
}

.reviews-modal label {
font-size: 0.85rem;
font-weight: 500;
color: var(--color-text, #f5f0eb);
letter-spacing: 0.5px;
}

.reviews-modal input,
.reviews-modal textarea {
width: 100%;
padding: 10px 14px;
background-color: var(--color-bg, #1a1816);
border: 1px solid var(--color-border, #3d3835);
border-radius: 8px;
color: var(--color-text, #f5f0eb);
font-family: var(--font-sans);
font-size: 0.95rem;
transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.reviews-modal input:focus,
.reviews-modal textarea:focus {
outline: none;
border-color: var(--color-primary, #d4af37);
box-shadow: 0 0 0 3px rgba(212, 175, 55, 0.15);
}

.reviews-modal .star-input {
display: flex;
gap: 6px;
padding: 4px 0;
}

.reviews-modal .star-btn {
background: none;
border: none;
font-size: 2rem;
color: var(--color-border, #3d3835);
cursor: pointer;
padding: 0;
transition: color 0.2s ease, transform 0.2s ease;
line-height: 1;
}

.reviews-modal .star-btn.active,
.reviews-modal .star-btn:hover {
color: var(--color-primary, #d4af37);
transform: scale(1.15);
}

.reviews-modal .form-note {
font-size: 0.85rem;
margin-top: 4px;
text-align: center;
}

.reviews-modal .btn-primary {
align-self: center;
padding: 12px 36px;
}


Loading