Skip to content

Instantly share code, notes, and snippets.

@dmdboi
Created August 16, 2024 08:54
Show Gist options
  • Save dmdboi/21447b8513e353e2c5a8e26c71a9e18a to your computer and use it in GitHub Desktop.
Save dmdboi/21447b8513e353e2c5a8e26c71a9e18a to your computer and use it in GitHub Desktop.
A vue compnent example for adding Headless Comments to your website
import axios from "axios";
const API_TOKEN = "";
const SITE_ID = "";
const api = axios.create({
baseURL: "https://headlesscomments.io/api/",
headers: {
"Content-type": "application/json",
Authorization: `Bearer ${API_TOKEN}`,
"x-site-id": SITE_ID,
},
});
export default class Comments {
headers(slug: string) {
return {
headers: {
"x-slug": slug,
},
};
}
async getPageComments(slug: string) {
return (await api.get(`/comments?page=${slug}`, this.headers(slug))).data;
}
async postComment(slug: string, data: CreateCommentRequest) {
return await api.post(`/comments`, data, this.headers(slug));
}
}
export interface CreateCommentRequest {
name: string;
email: string;
content: string;
parent_id?: string;
}
export interface Comment {
id: string;
author_name: string;
author_email: string;
content: string;
parent_id: string;
created_at: string;
children: Comment[];
approved: boolean;
}
<template>
<div>
<h2>Comments</h2>
<!-- Comments List -->
<ul v-if="isLoaded">
<li v-for="comment in comments" :key="comment.id">
<span>{{ comment.content }}</span>
<div>
<strong>{{ comment.author_name }}</strong> -
<span>{{ new Date(comment.created_at).toLocaleDateString() }}</span>
</div>
</li>
</ul>
<!-- Loading Spinner -->
<div v-else>Loading...</div>
<!-- Message Box -->
<div class="message-box">
<form @submit.prevent="submit">
<div class="author-info">
<input type="text" placeholder="Name" v-model="comment.name" />
<input type="email" placeholder="Email" v-model="comment.email" />
</div>
<textarea rows="4" placeholder="Write your comment here..." v-model="comment.content"></textarea>
<div class="button-container">
<button>Submit</button>
</div>
</form>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import Comments from "../../comments";
import type { Comment } from "../../comments";
const hc = new Comments();
const path = window.location.pathname.replace(/\/$/, "");
const isLoaded = ref(false);
const isSending = ref(false);
const comments = ref([] as Comment[]);
const comment = ref({
name: "",
email: "",
content: "",
});
async function fetchComments() {
isLoaded.value = false;
comments.value = (await hc.getPageComments(path)).data;
isLoaded.value = true;
}
async function submit() {
isSending.value = true;
const response = await hc.postComment(path, comment.value);
if (response.status === 200) {
alert("Comment submitted successfully!");
} else {
alert("Failed to submit comment. Please try again.");
}
// Clear the form
comment.value = {
name: "",
email: "",
content: "",
};
comments.value = (await hc.getPageComments(path)).data;
isSending.value = false;
}
onMounted(async () => {
await fetchComments();
});
</script>
<style scoped>
ul {
list-style: none;
padding: 0;
}
li {
margin-bottom: 1rem;
padding: 1rem;
border: 1px solid #ccc;
}
.message-box {
margin-top: 1rem;
border: 1px solid #ccc;
padding: 1rem;
}
.message-box textarea {
margin-bottom: 0.5rem;
border-radius: 4px;
border: 1px solid #ccc;
resize: vertical;
}
.message-box .author-info {
display: grid;
gap: 0.5rem;
}
.author-info input {
margin-bottom: 0.5rem;
border-radius: 4px;
border: 1px solid #ccc;
padding: 0.5rem;
}
.button-container {
display: flex;
justify-content: flex-end;
}
.message-box button {
padding: 0.5rem 1rem;
background-color: #007bff;
color: white;
border: none;
cursor: pointer;
border-radius: 4px;
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment