-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add comment, detail view, logos
- Loading branch information
Showing
6 changed files
with
327 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import { collection, getDocs } from "firebase/firestore"; | ||
import { defineStore } from "pinia"; | ||
import { ref } from "vue"; | ||
|
||
import { firestore } from "./firebase"; | ||
import { Comment } from "./types"; | ||
|
||
export const useCommentStore = defineStore("comments", () => { | ||
const comments = ref<Comment[]>([]); | ||
|
||
const fetchComments = () => { | ||
const commentCollection = collection(firestore, "comments"); | ||
|
||
return getDocs(commentCollection) | ||
.then((querySnapshot) => { | ||
return querySnapshot.docs.map( | ||
(doc) => | ||
({ | ||
_id: doc.id, | ||
...doc.data(), | ||
}) as Comment, | ||
); | ||
}) | ||
.catch((error) => { | ||
console.log("Error getting documents: ", error); | ||
|
||
return [] as Comment[]; | ||
}); | ||
}; | ||
|
||
const refetch = () => { | ||
fetchComments().then((data) => { | ||
comments.value = data; | ||
}); | ||
}; | ||
refetch(); | ||
|
||
const getCommentsByProjectUid = (projectUid: string) => { | ||
return comments.value.filter((comment) => comment.projectId === projectUid); | ||
}; | ||
|
||
// function upvoteProject(_id: string, uid?: string) { | ||
// const project = comments.value.find((p) => p._id === _id); | ||
// if (!project) return; | ||
// const projectData = { | ||
// ...project, | ||
// upvotes: uid | ||
// ? project.upvotes.includes(uid) | ||
// ? project.upvotes.filter((projectUid) => projectUid !== uid) | ||
// : [...project.upvotes, uid] | ||
// : project.upvotes, | ||
// }; | ||
// setDoc(doc(firestore, `projects/${_id}`), projectData) | ||
// .then(() => { | ||
// comments.value = comments.value.map((p) => | ||
// p._id === _id ? projectData : p, | ||
// ); | ||
// // refetch(); | ||
// }) | ||
// .catch((error) => { | ||
// console.error("Error writing document: ", error); | ||
// }); | ||
// } | ||
|
||
return { | ||
projects: comments, | ||
refetch, | ||
getCommentsByProjectUid, | ||
}; | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
<script setup lang="ts"> | ||
import { useField, useForm } from "vee-validate"; | ||
import { string } from "yup"; | ||
import { useCommentStore } from "@/comments"; | ||
const commentStore = useCommentStore(); | ||
const props = defineProps<{ | ||
projectUid: string; | ||
}>(); | ||
type FormData = { | ||
comment: string; | ||
}; | ||
const { handleSubmit } = useForm<FormData>({ | ||
validationSchema: { | ||
comment: string().required("Please enter a comment."), | ||
}, | ||
initialValues: { | ||
comment: "", | ||
}, | ||
}); | ||
const onSubmit = handleSubmit( | ||
// Success | ||
(values: FormData) => { | ||
// handle form submission here | ||
commentStore.addCommentToProject(values.comment, props.projectUid); | ||
}, | ||
// Failure | ||
(errors) => { | ||
console.log(errors); | ||
}, | ||
); | ||
const { value: comment, errorMessage: commentError } = | ||
useField<string>("comment"); | ||
</script> | ||
|
||
<template> | ||
<div class="mt-6 flex gap-x-3"> | ||
<img | ||
src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" | ||
alt="" | ||
class="h-6 w-6 flex-none rounded-full bg-gray-50" | ||
/> | ||
|
||
<div class="w-full"> | ||
<form class="relative flex-auto" @submit="onSubmit"> | ||
<div | ||
class="overflow-hidden rounded-lg pb-12 shadow-sm ring-1 ring-inset ring-gray-300 focus-within:ring-2 focus-within:ring-indigo-600" | ||
> | ||
<label for="comment" class="sr-only">Add your comment</label> | ||
|
||
<textarea | ||
id="comment" | ||
v-model="comment" | ||
rows="2" | ||
name="comment" | ||
class="block w-full resize-none border-0 bg-transparent py-1.5 text-gray-900 placeholder:text-gray-400 focus:ring-0 sm:text-sm sm:leading-6" | ||
placeholder="Add your comment..." | ||
/> | ||
</div> | ||
|
||
<div | ||
class="absolute inset-x-0 bottom-0 flex justify-between py-2 pl-3 pr-2" | ||
> | ||
<button | ||
type="submit" | ||
class="rounded-md bg-white px-2.5 py-1.5 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50" | ||
> | ||
Comment | ||
</button> | ||
</div> | ||
</form> | ||
|
||
<p v-if="commentError" class="error">{{ commentError }}</p> | ||
</div> | ||
</div> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
<script setup lang="ts"> | ||
import { computed } from "vue"; | ||
import { useCommentStore } from "@/comments"; | ||
import AddCommentForm from "./AddCommentForm.vue"; | ||
const props = defineProps<{ | ||
projectUid: string; | ||
}>(); | ||
const commentStore = useCommentStore(); | ||
const activity = computed(() => | ||
commentStore.getCommentsByProjectUid(props.projectUid), | ||
); | ||
</script> | ||
|
||
<template> | ||
<ul v-if="activity.length > 0" role="list" class="mt-6 space-y-6"> | ||
<li | ||
v-for="(comment, activityItemIdx) in activity" | ||
:key="comment._id" | ||
class="relative flex gap-x-4" | ||
> | ||
<div | ||
:class="[ | ||
activityItemIdx === activity.length - 1 ? 'h-6' : '-bottom-6', | ||
'absolute left-0 top-0 flex w-6 justify-center', | ||
]" | ||
> | ||
<div class="w-px bg-gray-200" /> | ||
</div> | ||
|
||
<img | ||
:src="comment.person.imageUrl" | ||
alt="" | ||
class="relative mt-3 h-6 w-6 flex-none rounded-full bg-gray-50" | ||
/> | ||
|
||
<div class="flex-auto rounded-md p-3 ring-1 ring-inset ring-gray-200"> | ||
<div class="flex justify-between gap-x-4"> | ||
<div class="py-0.5 text-xs leading-5 text-gray-500"> | ||
<span class="font-medium text-gray-900">{{ | ||
comment.person.name | ||
}}</span> | ||
commented | ||
</div> | ||
|
||
<time | ||
:datetime="comment.dateTime" | ||
class="flex-none py-0.5 text-xs leading-5 text-gray-500" | ||
>{{ comment.date }}</time | ||
> | ||
</div> | ||
|
||
<p class="text-sm leading-6 text-gray-500"> | ||
{{ comment.comment }} | ||
</p> | ||
</div> | ||
</li> | ||
</ul> | ||
|
||
<div v-else class="mt-6 text-sm leading-5 text-gray-500">No comments yet</div> | ||
|
||
<AddCommentForm :project-uid="$props.projectUid" /> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,103 @@ | ||
<template>Welcome to {{ $route.params.id }}</template> | ||
<script setup lang="ts"> | ||
import { computed } from "vue"; | ||
import { useRoute } from "vue-router"; | ||
import { useProjectStore } from "@/projects"; | ||
import Comments from "./Comments.vue"; | ||
const store = useProjectStore(); | ||
const route = useRoute(); | ||
const project = computed(() => | ||
store.projects.find((project) => project.projectId === route.params.id), | ||
); | ||
</script> | ||
|
||
<template> | ||
<div class="px-4 py-5 sm:px-6"> | ||
<h1 class="text-3xl font-bold tracking-tight text-gray-900"> | ||
{{ project?.title }} | ||
</h1> | ||
|
||
<p class="mt-1 text-sm text-gray-500"> | ||
{{ project?.description }} | ||
</p> | ||
</div> | ||
|
||
<div class="border-b border-gray-100"> | ||
<dl class="divide-y divide-gray-100"> | ||
<!-- About Section --> | ||
<div class="px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6"> | ||
<dt class="text-sm font-medium text-gray-900">About</dt> | ||
|
||
<dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"> | ||
{{ project?.textContent }} | ||
</dd> | ||
</div> | ||
|
||
<!-- Links Section --> | ||
<div | ||
v-if="project?.links && project.links.length > 0" | ||
class="px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6" | ||
> | ||
<dt class="text-sm font-medium leading-6 text-gray-900">Links</dt> | ||
|
||
<dd class="mt-2 text-sm text-gray-900 sm:col-span-2 sm:mt-0"> | ||
<ul | ||
role="list" | ||
class="divide-y divide-gray-100 rounded-md border border-gray-200" | ||
> | ||
<li | ||
v-for="link in project?.links" | ||
:key="link" | ||
class="flex items-center justify-between py-4 pl-4 pr-5 text-sm leading-6" | ||
> | ||
{{ link }} | ||
</li> | ||
</ul> | ||
</dd> | ||
</div> | ||
|
||
<!-- Tags Section --> | ||
<div | ||
v-if="project?.tags && project.tags.length > 0" | ||
class="px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6" | ||
> | ||
<dt class="text-sm font-medium leading-6 text-gray-900">Tags</dt> | ||
|
||
<dd class="mt-2 text-sm text-gray-900 sm:col-span-2 sm:mt-0"> | ||
<ul role="list" class="flex space-x-2"> | ||
<li | ||
v-for="tag in project?.tags" | ||
:key="tag" | ||
class="rounded-md bg-blue-200 px-2 py-1 text-sm leading-6 text-blue-800" | ||
> | ||
{{ tag }} | ||
</li> | ||
</ul> | ||
</dd> | ||
</div> | ||
|
||
<!-- Upvotes Section --> | ||
<div | ||
v-if="project?.upvotes && project.upvotes.length > 0" | ||
class="px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6" | ||
> | ||
<dt class="text-sm font-medium leading-6 text-gray-900">Upvotes</dt> | ||
|
||
<dd class="mt-2 text-sm text-gray-900 sm:col-span-2 sm:mt-0"> | ||
{{ project?.upvotes.length }} people upvoted this project. | ||
</dd> | ||
</div> | ||
|
||
<!-- Any Other Sections You Want to Add --> | ||
</dl> | ||
</div> | ||
|
||
<div class="mt-10 px-4 py-6 sm:px-6"> | ||
<h2 class="text-xl font-semibold leading-6 text-gray-900">Comments</h2> | ||
|
||
<Comments v-if="project?._id" :project-uid="project._id" /> | ||
</div> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters