Skip to content

Commit

Permalink
feat: implement project store with pinia
Browse files Browse the repository at this point in the history
  • Loading branch information
thraizz committed Jan 27, 2024
1 parent ed039b0 commit fac3619
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 41 deletions.
51 changes: 51 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"@heroicons/vue": "^2.1.1",
"axios": "^1.6.5",
"firebase": "^10.7.2",
"pinia": "^2.1.7",
"vee-validate": "^4.12.4",
"vue": "^3.3.11",
"vue-router": "^4.2.5",
Expand Down
5 changes: 4 additions & 1 deletion src/firebase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { getAnalytics } from "firebase/analytics";
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
import { getFirestore } from "firebase/firestore";

// For Firebase JS SDK v7.20.0 and later, measurementId is optional
Expand All @@ -21,4 +22,6 @@ export const app = initializeApp(firebaseConfig);

export const analytics = getAnalytics(app);

export const db = getFirestore(app);
export const firestore = getFirestore(app);

export const auth = getAuth(app);
5 changes: 4 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import "./style.css";

import { createPinia } from "pinia";
import { createApp } from "vue";
import { createRouter, createWebHistory } from "vue-router";

import App from "./App.vue";
import HomeVue from "./views/Home.vue";

const app = createApp(App);
const router = createRouter({
history: createWebHistory(),
routes: [
Expand Down Expand Up @@ -42,4 +44,5 @@ const router = createRouter({
},
],
});
createApp(App).use(router).mount("#app");
const pinia = createPinia();
app.use(router).use(pinia).mount("#app");
66 changes: 66 additions & 0 deletions src/projects.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { collection, doc, getDocs, setDoc } from "firebase/firestore";
import { defineStore } from "pinia";
import { ref } from "vue";

import { firestore } from "./firebase";
import { Project } from "./types";

export const useProjectStore = defineStore("projects", () => {
const projects = ref<Project[]>([]);

const fetchProjects = () => {
const projectsCollection = collection(firestore, "projects");

return getDocs(projectsCollection)
.then((querySnapshot) => {
return querySnapshot.docs.map(
(doc) =>
({
_id: doc.id,
...doc.data(),
}) as Project,
);
})
.catch((error) => {
console.log("Error getting documents: ", error);

return [] as Project[];
});
};

const refetch = () => {
fetchProjects().then((data) => {
projects.value = data;
});
};
refetch();

function upvoteProject(_id: string, uid?: string) {
const project = projects.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(() => {
projects.value = projects.value.map((p) =>
p._id === _id ? projectData : p,
);
// refetch();
})
.catch((error) => {
console.error("Error writing document: ", error);
});
}

return {
projects,
refetch,
upvoteProject,
};
});
23 changes: 4 additions & 19 deletions src/views/ProjectsList.vue
Original file line number Diff line number Diff line change
@@ -1,31 +1,16 @@
<script setup lang="ts">
import { collection, getDocs } from "firebase/firestore";
import { onMounted, ref } from "vue";
import { db } from "@/firebase";
import { Project } from "@/types";
import { useProjectStore } from "@/projects";
import ProjectCard from "./ProjectCard.vue";
const projects = ref<any[]>([]);
onMounted(async () => {
const querySnapshot = await getDocs(collection(db, "projects"));
projects.value = querySnapshot.docs.map(
(doc) =>
({
_id: doc.id,
...doc.data(),
}) as Project,
);
});
const store = useProjectStore();
</script>

<template>
<ul role="list" class="w-full divide-y divide-gray-100">
<ProjectCard
v-for="project in projects"
:key="project"
v-for="project in store.projects"
:key="project._id"
:project="project"
/>
</ul>
Expand Down
25 changes: 5 additions & 20 deletions src/views/UpvoteButton.vue
Original file line number Diff line number Diff line change
@@ -1,31 +1,15 @@
<script setup lang="ts">
import { HeartIcon } from "@heroicons/vue/20/solid";
import { doc, setDoc } from "firebase/firestore";
import { useUser } from "@/components/user";
import { db } from "@/firebase";
import { useProjectStore } from "@/projects";
import { Project } from "@/types";
const props = defineProps<{
defineProps<{
project: Project;
}>();
const { user } = useUser();
const upvoteProject = () => {
setDoc(doc(db, `projects/${props.project._id}`), {
...props.project,
upvotes: user.value
? props.project.upvotes.includes(user.value.uid)
? props.project.upvotes.filter((uid) => uid !== user.value?.uid)
: [...props.project.upvotes, user.value.uid]
: props.project.upvotes,
})
.then(() => {
console.log("Document successfully written!");
})
.catch((error) => {
console.error("Error writing document: ", error);
});
};
const store = useProjectStore();
</script>

<template>
Expand All @@ -37,7 +21,8 @@ const upvoteProject = () => {
? 'bg-indigo-200'
: 'bg-indigo-100',
]"
@click="upvoteProject"
:disabled="!user || user.isAnonymous"
@click="store.upvoteProject(project._id, user?.uid)"
>
<HeartIcon
class="size-5"
Expand Down

0 comments on commit fac3619

Please sign in to comment.