add link upvote/downvote and authenticated comp

This commit is contained in:
YuukanOO 2021-01-22 09:50:14 +01:00
parent 8d58ff3590
commit 98c29f5694
7 changed files with 105 additions and 7 deletions

View File

@ -3,9 +3,20 @@
<nav> <nav>
<router-link :to="{ name: 'links' }">Derniers liens publiés</router-link> <router-link :to="{ name: 'links' }">Derniers liens publiés</router-link>
/ /
<authenticated>
<template v-slot="{ username }">
<p>Vous êtes connecté en tant que {{ username }}</p>
-
<button @click.prevent="$store.commit('auth/logout')">
Se déconnecter
</button>
</template>
<template v-slot:anonymous>
<router-link :to="{ name: 'register' }">Créer un compte</router-link> <router-link :to="{ name: 'register' }">Créer un compte</router-link>
/ /
<router-link :to="{ name: 'login' }">Se connecter</router-link> <router-link :to="{ name: 'login' }">Se connecter</router-link>
</template>
</authenticated>
</nav> </nav>
<router-view></router-view> <router-view></router-view>
<notifications-panel /> <notifications-panel />
@ -14,8 +25,9 @@
<script> <script>
import NotificationsPanel from "./components/NotificationsPanel"; import NotificationsPanel from "./components/NotificationsPanel";
import Authenticated from "./components/Authenticated";
export default { export default {
components: { NotificationsPanel }, components: { NotificationsPanel, Authenticated },
}; };
</script> </script>

View File

@ -16,6 +16,14 @@ class Api {
return this._get(`/api/links/${id}`); return this._get(`/api/links/${id}`);
} }
upvoteLink(id) {
return this._put(`/api/links/${id}/upvote`);
}
downvoteLink(id) {
return this._put(`/api/links/${id}/downvote`);
}
getLinkComments(id) { getLinkComments(id) {
return this._get(`/api/links/${id}/comments`); return this._get(`/api/links/${id}/comments`);
} }
@ -80,6 +88,30 @@ class Api {
return r.json(); return r.json();
}); });
} }
_put(path, data) {
return fetch(this._baseUrl + path, {
method: "PUT",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
...this._authorizationHeader(),
},
body: JSON.stringify(data),
}).then((r) => {
if (!r.ok) {
return Promise.reject(new Error("Erreur dans la requête"));
}
if (r.status === 204) {
return r;
}
// if (!r.headers['Content-Length'] === '0') {
return r.json();
});
}
} }
export default new Api(process.env.VUE_APP_API_URL); export default new Api(process.env.VUE_APP_API_URL);

View File

@ -0,0 +1,9 @@
<template>
<div>
<slot
:username="$store.state.auth.username"
v-if="$store.state.auth.token"
></slot>
<slot v-else name="anonymous"></slot>
</div>
</template>

View File

@ -6,18 +6,48 @@
}}</router-link> }}</router-link>
</h2> </h2>
<p>Publié le {{ link.createdAt }} par {{ link.createdBy.username }}</p> <p>Publié le {{ link.createdAt }} par {{ link.createdBy.username }}</p>
<authenticated>
<button @click.prevent="upvote">👍 {{ link.upvotesCount }}</button>
/ <button @click.prevent="downvote">👎 {{ link.downvotesCount }}</button>
<template v-slot:anonymous>
<p>👍 {{ link.upvotesCount }} / 👎 {{ link.downvotesCount }}</p> <p>👍 {{ link.upvotesCount }} / 👎 {{ link.downvotesCount }}</p>
</template>
</authenticated>
</article> </article>
</template> </template>
<script> <script>
import Authenticated from "./Authenticated";
import api from "../api";
export default { export default {
name: "LinkItem", name: "LinkItem",
components: { Authenticated },
props: { props: {
link: { link: {
type: Object, type: Object,
required: true, required: true,
}, },
}, },
methods: {
async upvote() {
await api.upvoteLink(this.link.id);
// const link = await api.getLinkById(this.link.id);
// this.link.downvotesCount = link.downvotesCount;
// this.link.upvotesCount = link.upvotesCount;
this.$emit("refresh", this.link.id);
},
async downvote() {
await api.downvoteLink(this.link.id);
// const link = await api.getLinkById(this.link.id);
// this.link.upvotesCount = link.upvotesCount;
// this.link.downvotesCount = link.downvotesCount;
this.$emit("refresh", this.link.id);
},
},
}; };
</script> </script>

View File

@ -7,7 +7,7 @@
message="Chargement du lien en cours ..." message="Chargement du lien en cours ..."
/> />
<div v-else> <div v-else>
<link-item :link="link" /> <link-item :link="link" @refresh="refreshLink" />
<loading v-if="comments === null" message="Chargement des commentaires" /> <loading v-if="comments === null" message="Chargement des commentaires" />
<p v-else-if="comments.length === 0">Aucun commentaire pour ce lien</p> <p v-else-if="comments.length === 0">Aucun commentaire pour ce lien</p>
<ul v-else> <ul v-else>
@ -52,6 +52,9 @@ export default {
// '$route': 'fetchLinkDetail' // '$route': 'fetchLinkDetail'
}, },
methods: { methods: {
async refreshLink() {
this.link = await api.getLinkById(this.id);
},
async fetchLinkDetail() { async fetchLinkDetail() {
this.link = null; this.link = null;
this.comments = null; this.comments = null;

View File

@ -8,7 +8,7 @@
/> />
<ul v-else> <ul v-else>
<li v-for="link in links" :key="link.id"> <li v-for="link in links" :key="link.id">
<link-item :link="link" /> <link-item :link="link" @refresh="refreshLink" />
</li> </li>
</ul> </ul>
</div> </div>
@ -41,6 +41,14 @@ export default {
// this.loading = false; // this.loading = false;
// } // }
}, },
methods: {
async refreshLink(id) {
const link = await api.getLinkById(id);
const index = this.links.findIndex((l) => l.id === id);
this.links.splice(index, 1, link);
},
},
}; };
</script> </script>

View File

@ -40,6 +40,10 @@ export default function createStore() {
state.token = token; state.token = token;
state.username = username; state.username = username;
}, },
logout(state) {
state.token = null;
state.username = null;
},
}, },
actions: { actions: {
async login({ commit }, data) { async login({ commit }, data) {