133 lines
5.5 KiB
Plaintext
133 lines
5.5 KiB
Plaintext
<div id="review-box-{{ block.id }}" class="review-box" data-block-id="{{ block.id }}">
|
|
<h3>Customer Reviews</h3>
|
|
|
|
{% if customer %}
|
|
<form id="review-form-{{ block.id }}" class="review-form-singleton">
|
|
<input type="hidden" name="productId" value="{{ product.id }}" />
|
|
<div class="review-form-fields">
|
|
<input type="text" name="name" placeholder="Your name" value="{{ customer.first_name }} {{ customer.last_name }}" required />
|
|
<textarea name="review" placeholder="Write your review" required></textarea>
|
|
<button type="submit" class="submit-review-btn">Submit Review</button>
|
|
</div>
|
|
</form>
|
|
{% else %}
|
|
<div class="login-prompt">
|
|
<p>Please <a href="{{ routes.account_login_url }}">login</a> to write a review for this product.</p>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div id="reviews-list-{{ block.id }}" class="reviews-list-container">
|
|
<p class="loading-reviews">Checking your verified reviewer status...</p>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.review-box { margin: 20px 0; font-family: sans-serif; max-width: 600px; }
|
|
.review-form-singleton { display: flex; flex-direction: column; gap: 10px; margin-bottom: 20px; }
|
|
.review-form-fields { display: flex; flex-direction: column; gap: 10px; }
|
|
.review-form-fields input, .review-form-fields textarea { padding: 8px; border: 1px solid #ccc; border-radius: 4px; width: 100%; }
|
|
.review-form-fields button { padding: 10px; background: #000; color: #fff; border: none; border-radius: 4px; cursor: pointer; }
|
|
.review-form-fields button:disabled { background: #666; cursor: not-allowed; }
|
|
.login-prompt { padding: 15px; border: 1px dashed #ccc; color: #555; margin-bottom: 20px; text-align: center; }
|
|
.review-item { border-bottom: 1px solid #eee; padding: 15px 0; margin-bottom: 10px; }
|
|
.review-item strong { display: block; margin-bottom: 5px; color: #333; }
|
|
.review-item p { margin: 0; color: #666; line-height: 1.4; }
|
|
.optimistic-item { background: #f9f9f9; border-left: 4px solid #000; padding-left: 15px !important; }
|
|
</style>
|
|
|
|
<script>
|
|
(function() {
|
|
// SINGLETON CHECK: If we already have initialized a review block on this page, hide the second one.
|
|
if (window.shopifyProductReviewInitialized) {
|
|
document.querySelector('[data-block-id="{{ block.id }}"]').style.display = 'none';
|
|
return;
|
|
}
|
|
window.shopifyProductReviewInitialized = true;
|
|
|
|
const blockId = "{{ block.id }}";
|
|
const productId = "{{ product.id }}";
|
|
const shop = "{{ shop.permanent_domain }}";
|
|
const container = document.getElementById(`reviews-list-${blockId}`);
|
|
const form = document.getElementById(`review-form-${blockId}`);
|
|
|
|
async function loadReviews() {
|
|
try {
|
|
const response = await fetch(`/apps/reviews?productId=${productId}&shop=${shop}`);
|
|
const text = await response.json().catch(() => null);
|
|
|
|
if (!text || (typeof text === 'string' && text.trim().startsWith("<!doctype"))) {
|
|
container.innerHTML = "<p style='color:red'><b>⚠️ Permissions Error:</b> Please open the app in your Shopify Admin dashboard once to activate it, then refresh this page.</p>";
|
|
return;
|
|
}
|
|
|
|
const reviews = text;
|
|
container.innerHTML = "";
|
|
|
|
if (reviews.error) {
|
|
container.innerHTML = `<p>${reviews.error}</p>`;
|
|
return;
|
|
}
|
|
|
|
if (!Array.isArray(reviews) || reviews.length === 0) {
|
|
container.innerHTML = "<p>No reviews yet. Be the first!</p>";
|
|
return;
|
|
}
|
|
|
|
reviews.forEach(r => {
|
|
const item = document.createElement("div");
|
|
item.className = "review-item";
|
|
item.innerHTML = `<strong>${escape(r.name)}</strong><p>${escape(r.review)}</p>`;
|
|
container.appendChild(item);
|
|
});
|
|
} catch (err) {
|
|
container.innerHTML = "<p>Ready to write a review.</p>";
|
|
}
|
|
}
|
|
|
|
function escape(t) {
|
|
const d = document.createElement('div');
|
|
d.textContent = t;
|
|
return d.innerHTML;
|
|
}
|
|
|
|
if (form) {
|
|
form.addEventListener("submit", async function(e) {
|
|
e.preventDefault();
|
|
const btn = this.querySelector(".submit-review-btn");
|
|
btn.disabled = true;
|
|
btn.textContent = "Verifying purchase...";
|
|
|
|
try {
|
|
const formData = new FormData(this);
|
|
const response = await fetch(`/apps/reviews?shop=${shop}&logged_in_customer_id={{ customer.id }}`, { method: "POST", body: formData });
|
|
const textData = await response.json().catch(() => ({error: "App connection issue. Open App Dashboard once."}));
|
|
|
|
console.log("Submit Response:", textData);
|
|
if (textData.error) {
|
|
const details = textData.details ? `\n\nDetails: ${JSON.stringify(textData.details)}` : "";
|
|
alert(`${textData.error}${details}`);
|
|
} else if (textData.success) {
|
|
const newItem = document.createElement("div");
|
|
newItem.className = "review-item optimistic-item";
|
|
newItem.innerHTML = `<strong>${escape(formData.get("name"))} (Just now)</strong><p>${escape(formData.get("review"))}</p>`;
|
|
container.insertBefore(newItem, container.firstChild);
|
|
this.reset();
|
|
alert("Review submitted successfully!");
|
|
setTimeout(loadReviews, 3000);
|
|
}
|
|
} catch (err) {
|
|
alert("Connection error: Try refreshing the page.");
|
|
} finally {
|
|
btn.disabled = false;
|
|
btn.textContent = "Submit Review";
|
|
}
|
|
});
|
|
}
|
|
|
|
loadReviews();
|
|
})();
|
|
</script>
|
|
|
|
{% schema %}
|
|
{ "name": "Reviews", "target": "section", "settings": [] }
|
|
{% endschema %} |