Skip to content

Commit

Permalink
Send messages
Browse files Browse the repository at this point in the history
  • Loading branch information
juanwmedia committed Oct 29, 2020
1 parent b03fe6a commit de63f78
Show file tree
Hide file tree
Showing 5 changed files with 253 additions and 29 deletions.
54 changes: 28 additions & 26 deletions src/components/RoomsComponent.vue
Expand Up @@ -7,35 +7,37 @@
<div v-else class="columns is-multiline">
<!-- Room element -->
<div v-for="room in rooms" :key="room.id" class="column is-one-third">
<div class="card">
<div class="card-image">
<figure class="image is-16by9">
<img
src="https://bulma.io/images/placeholders/1280x960.png"
alt="Placeholder image"
/>
</figure>
</div>
<div class="card-content">
<div class="media">
<div class="media-content">
<p class="title is-4">{{ room.name }}</p>
<p class="subtitle is-6">by {{ room.adminName }}</p>
</div>
<router-link :to="{ name: 'view', params: { id: room.id } }">
<div class="card">
<div class="card-image">
<figure class="image is-16by9">
<img
src="https://bulma.io/images/placeholders/1280x960.png"
alt="Placeholder image"
/>
</figure>
</div>
<div class="content">
{{ room.description }}
<div class="card-content">
<div class="media">
<div class="media-content">
<p class="title is-4">{{ room.name }}</p>
<p class="subtitle is-6">by {{ room.adminName }}</p>
</div>
</div>
<div class="content">
{{ room.description }}
</div>
<nav class="buttons is-right">
<router-link
:to="{ name: 'update', params: { id: room.id } }"
class="button is-small"
v-if="room.adminUid === $store.getters['user/getUserUid']"
>Edit</router-link
>
</nav>
</div>
<nav class="buttons is-right">
<router-link
:to="{ name: 'update', params: { id: room.id } }"
class="button is-small"
v-if="room.adminUid === $store.getters['user/getUserUid']"
>Edit</router-link
>
</nav>
</div>
</div>
</router-link>
</div>
<!-- End of room element -->
</div>
Expand Down
10 changes: 10 additions & 0 deletions src/router/index.js
Expand Up @@ -5,6 +5,7 @@ const AuthView = () => import("../views/AuthView.vue");
const UserProfileView = () => import("../views/UserProfileView.vue");
const CreateRoom = () => import("../views/CreateRoom.vue");
const UpdateRoom = () => import("../views/UpdateRoom.vue");
const ViewRoom = () => import("../views/ViewRoom.vue");
import store from "../store";

Vue.use(VueRouter);
Expand Down Expand Up @@ -47,6 +48,15 @@ const routes = [
meta: {
requiresAuth: true
}
},
{
path: "/view/:id",
name: "view",
props: true,
component: ViewRoom,
meta: {
requiresAuth: true
}
}
];

Expand Down
2 changes: 2 additions & 0 deletions src/store/index.js
Expand Up @@ -29,6 +29,8 @@ const store = new Vuex.Store({
commit("user/setUser", null);
commit("rooms/setRooms", []);
commit("rooms/setRoomsListener", () => {});
commit("messages/setMessages", []);
commit("messages/setMessagesListener", () => {});
}
});
}
Expand Down
55 changes: 52 additions & 3 deletions src/store/messages.js
@@ -1,12 +1,61 @@
import { db } from "../firebase.js";

const state = {
messages: []
messages: [],
messagesListener: () => {}
};

const getters = {};

const mutations = {};
const mutations = {
setMessages(state, messages) {
state.messages = messages;
},
setMessagesListener(state, listener) {
if (listener) {
state.listener = listener;
} else {
state.messagesListener();
}
}
};

const actions = {
async getMessages({ commit }, roomID) {
const query = db
.collection("rooms")
.doc(roomID)
.collection("messages")
.orderBy("createdAt", "desc")
.onSnapshot(doSnapShot);

commit("setMessagesListener", query);

const actions = {};
function doSnapShot(querySnapshot) {
const messages = [];
querySnapshot.forEach(doc => {
let message = doc.data();
message.id = doc.id;
messages.unshift(message);
});

commit("setMessages", messages);
}
},

async createMessage({ rootState }, { roomID, message }) {
await db
.collection("rooms")
.doc(roomID)
.collection("messages")
.add({
userId: rootState.user.user.uid,
userName: rootState.user.user.displayName,
message,
createdAt: Date.now()
});
}
};

export default {
namespaced: true,
Expand Down
161 changes: 161 additions & 0 deletions src/views/ViewRoom.vue
@@ -0,0 +1,161 @@
<template>
<div>
<article class="section">
<div class="container">
<div class="columns">
<div v-if="room" class="column is-half is-offset-one-quarter">
<h1 class="title has-text-centered">{{ room.name }}</h1>
<div class="messages content" ref="messages">
<div
v-for="message in messages"
:key="message.id"
class="message"
:class="{
'message--own':
message.userId === $store.getters['user/getUserUid']
}"
>
<p>
{{ message.message }}
</p>
</div>
</div>
</div>
</div>
</div>
</article>
<section class="send">
<form @submit.prevent="createMessage" class="form">
<div class="control">
<textarea
v-model="message"
class="textarea form__textarea"
placeholder="Write your message here..."
></textarea>
</div>
<div class="control">
<button
:disabled="!message"
type="submit"
class="button is-info"
:class="{ 'is-loading': isLoading }"
>
Send
</button>
</div>
</form>
</section>
</div>
</template>

<script>
import { mapState } from "vuex";
export default {
name: "ViewRoom",
async created() {
try {
let room = this.$store.getters["rooms/getRoom"](this.id);
if (!room) {
room = await this.$store.dispatch("rooms/getRoom", this.id);
if (!room.exists) throw new Error("Could not find room");
room = room.data();
}
this.room = room;
this.$store.dispatch("messages/getMessages", this.id);
} catch (error) {
console.error(error.message);
this.$toast.error(error.message);
this.$router.push({ name: "home" });
}
},
destroyed() {
this.$store.commit("messages/setMessagesListener", null);
},
props: {
id: {
type: String,
required: true
}
},
data() {
return {
isLoading: false,
message: "",
room: null
};
},
methods: {
scrollDown() {
const messages = this.$refs.messages;
this.$nextTick(() => {
const height = messages.scrollHeight;
window.scrollTo({
top: height,
behavior: "smooth"
});
});
},
async createMessage() {
this.isLoading = true;
try {
await this.$store.dispatch("messages/createMessage", {
roomID: this.id,
message: this.message
});
this.scrollDown();
this.message = "";
} catch (error) {
console.error(error.message);
this.$toast.error(error.message);
} finally {
this.isLoading = false;
}
}
},
computed: {
...mapState("messages", ["messages"])
}
};
</script>

<style lang="scss" scoped>
.messages {
display: flex;
flex-direction: column;
flex-wrap: wrap;
padding-bottom: 90px;
}
.message {
padding: 1rem;
width: 75%;
&--own {
background-color: #baffc5;
width: 75%;
align-self: flex-end;
}
}
.send {
background-color: gray;
padding: 1rem;
position: fixed;
bottom: 0;
left: 0;
width: 100%;
}
.form {
display: flex;
justify-content: space-between;
align-items: center;
& > *:first-child {
flex-grow: 1;
margin-right: 1rem;
}
}
.textarea.form__textarea {
min-height: 4rem;
}
</style>

0 comments on commit de63f78

Please sign in to comment.