Skip to content

Commit

Permalink
feat: like button for candidate forms
Browse files Browse the repository at this point in the history
  • Loading branch information
harshtandiya committed Nov 7, 2024
1 parent 8d3f49e commit 5ce578c
Show file tree
Hide file tree
Showing 5 changed files with 238 additions and 2 deletions.
2 changes: 1 addition & 1 deletion ballot/api/candidate.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def get_candidate_details(candidate: str):
form = frappe.db.get_value(
"Election Candidate Application",
candidate,
["photo", "full_name", "designation", "organization", "submission_meta"],
["photo", "full_name", "designation", "organization", "submission_meta", "name"],
as_dict=1,
)

Expand Down
112 changes: 112 additions & 0 deletions ballot/api/like.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import frappe


@frappe.whitelist()
def toggle_like(reference_doctype: str, reference_name: str, comment_email: str) -> None:
"""
Add a 'Like' comment to the specified document.
Args:
reference_doctype (str): The doctype of the document being liked.
reference_name (str): The name of the document being liked.
comment_email (str): The email of the user liking the document.
Returns:
None
Raises:
ValueError: If any of the input parameters are invalid.
frappe.exceptions.ValidationError: If the document cannot be inserted.
"""
if not reference_doctype or not reference_name or not comment_email:
raise ValueError("All parameters must be provided and non-empty.")

try:
if is_already_liked(
reference_doctype=reference_doctype,
reference_name=reference_name,
comment_email=comment_email,
):
frappe.db.delete(
"Comment",
{
"reference_doctype": reference_doctype,
"reference_name": reference_name,
"comment_email": comment_email,
"comment_type": "Like",
},
)
else:
like = frappe.get_doc(
{
"doctype": "Comment",
"comment_type": "Like",
"reference_doctype": reference_doctype,
"reference_name": reference_name,
"comment_email": comment_email,
"content": "Liked",
}
)
like.insert(ignore_permissions=True)
except Exception as e:
frappe.log_error(message=str(e), title="Like Doc Insertion Failed")
frappe.throw(frappe.ValidationError)


@frappe.whitelist(allow_guest=True)
def get_likes_count(reference_doctype: str, reference_name: str) -> int:
"""
Get the count of likes for the specified document.
Args:
reference_doctype (str): The doctype of the document.
reference_name (str): The name of the document.
Returns:
int: The number of likes for the document.
"""

if not reference_doctype or not reference_name:
raise ValueError(
"Both reference_doctype and reference_name must be provided and non-empty."
)

return frappe.db.count(
"Comment",
filters={
"reference_doctype": reference_doctype,
"reference_name": reference_name,
"comment_type": "Like",
},
)


@frappe.whitelist()
def is_already_liked(reference_doctype: str, reference_name: str, comment_email: str) -> bool:
"""
Check if the specified document has already been liked by the given email.
Args:
reference_doctype (str): The doctype of the document.
reference_name (str): The name of the document.
comment_email (str): The email of the user.
Returns:
bool: True if the document is already liked by the given email, False otherwise.
"""

if not reference_doctype or not reference_name or not comment_email:
raise ValueError("All parameters must be provided and non-empty.")

return (
frappe.db.exists(
"Comment",
{
"reference_doctype": reference_doctype,
"reference_name": reference_name,
"comment_email": comment_email,
"comment_type": "Like",
},
)
is not None
)
62 changes: 62 additions & 0 deletions frontend/src/components/ui/LikeButton.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<template>
<button
class="flex divide-x-2 border rounded-sm hover:bg-gray-50 text-sm font-medium group transition-all ease-in-out duration-500"
:class="
alreadyLiked.data
? 'bg-red-600 text-white hover:bg-red-700 border-red-800 divide-red-800'
: ''
"
@click="handleLike()"
>
<div class="flex gap-1 py-2 px-4 items-center">
<IconHeart
size="1rem"
stroke="2"
class="group-hover:stroke-red-500"
:class="alreadyLiked.data ? 'fill-white group-hover:stroke-white' : ''"
/>
<span v-if="alreadyLiked.data">Liked</span>
<span v-else>Like</span>
</div>
<div class="p-2 min-w-12 gap-1 flex items-center justify-center">
<span>{{ likeCount.data }}</span>
</div>
</button>
</template>
<script setup>
import { inject } from 'vue'
import { checkAlreadyLiked, getLikeCount, toggleLike } from '@/utils/like'
import { IconHeart } from '@tabler/icons-vue'
const session = inject('$session')
const props = defineProps({
referenceDoctype: {
type: String,
required: true,
},
referenceName: {
type: String,
required: true,
},
})
const alreadyLiked = checkAlreadyLiked(
props.referenceDoctype,
props.referenceName,
session.user,
)
const likeCount = getLikeCount(props.referenceDoctype, props.referenceName)
const handleLike = () => {
const like = toggleLike(
props.referenceDoctype,
props.referenceName,
session.user,
)
like.fetch().then(() => {
likeCount.fetch()
alreadyLiked.fetch()
})
}
</script>
9 changes: 8 additions & 1 deletion frontend/src/pages/election/CandidatureSubmissionPublic.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@
:field="field"
/>
</div>
<LikeButton
v-if="session.user"
reference-doctype="Election Candidate Application"
:reference-name="formDetails.data.name"
/>
<CommentSection
doctype="Election Candidate Application"
:docname="route.params.id"
Expand All @@ -49,11 +54,13 @@ import Avatar from 'primevue/avatar'
import Header from '@/components/Header.vue'
import RenderFieldData from '@/components/candidature/RenderFieldData.vue'
import CommentSection from '@/components/comments/CommentSection.vue'
import LikeButton from '@/components/ui/LikeButton.vue'
import { createResource, LoadingText } from 'frappe-ui'
import { ref } from 'vue'
import { ref, inject } from 'vue'
import { useRoute } from 'vue-router'
const route = useRoute()
const session = inject('$session')
const breadcrumbItems = ref([
{
Expand Down
55 changes: 55 additions & 0 deletions frontend/src/utils/like.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { createResource } from 'frappe-ui'

export const toggleLike = (
reference_doctype,
reference_name,
comment_email,
) => {
return createResource({
url: 'ballot.api.like.toggle_like',
makeParams() {
return {
reference_doctype: reference_doctype,
reference_name: reference_name,
comment_email: comment_email,
}
},
onSuccess() {
return [1, 'Liked Successfully']
},
onError(err) {
return [0, err.messages]
},
})
}

export const checkAlreadyLiked = (
reference_doctype,
reference_name,
comment_email,
) => {
return createResource({
url: 'ballot.api.like.is_already_liked',
makeParams() {
return {
comment_email: comment_email,
reference_doctype: reference_doctype,
reference_name: reference_name,
}
},
auto: true,
})
}

export const getLikeCount = (reference_doctype, reference_name) => {
return createResource({
url: 'ballot.api.like.get_likes_count',
makeParams() {
return {
reference_doctype: reference_doctype,
reference_name: reference_name,
}
},
auto: true,
})
}

0 comments on commit 5ce578c

Please sign in to comment.