23. Join group

Previously, we were displaying users all the groups for whom he is a member or received an invitation for joining that group. Now we are going to give users the ability to join the group they are invited to.

First, in your GroupsComponent.vue where we are displaying the delete button, create another button that will be displayed only if the user’s invite status is “pending”.

<template v-else-if="getMemberStatus(user, group) == 'pending'">
	<form v-on:submit.prevent="acceptInvite">
		<input type="hidden" name="_id" v-bind:value="group._id" required />
		<input type="submit" v-bind:value="isLoading ? 'Accepting...' : 'Join'" v-bind:isLoading="disabled" class="btn btn-success" />
	</form>
</template>

<template v-else-if="getMemberStatus(user, group) == 'accepted'">
	<form v-on:submit.prevent="leaveGroup">
		<input type="hidden" name="_id" v-bind:value="group._id" required />
		<input type="submit" v-bind:value="isLoading ? 'Leaving...' : 'Leave group'" v-bind:isLoading="disabled" class="btn btn-danger" />
	</form>
</template>

We need to create the isLoading variable in our data() object.

isLoading: false,

Then we need to create the getMemberStatus method in our methods object.

getMemberStatus: function (user, group) {
	for (let a = 0; a < group.members.length; a++) {
		if (user != null && group.members[a].user._id == user._id) {
			return group.members[a].status
		}
	}
	return ""
},

Now you will see that button to join the group. Then we need to create a method that will be called when that form is submitted.

acceptInvite: function () {
	// get vue instance
	const self = this

	// create form data object
	const form = event.target
	const _id = form._id.value
	const formData = new FormData(form)

	// ask for user confirmation
	swal.fire({
		title: 'Join group',
		text: "Are you sure you want to join this group ?",
		icon: 'warning',
		showCancelButton: true,
		confirmButtonColor: '#3085d6',
		cancelButtonColor: '#d33',
		confirmButtonText: 'Yes'
	}).then(async function (result) {
		if (result.isConfirmed) {
			
			// call an AJAX
			const response = await axios.post(
                self.$apiURL + "/groups/acceptInvite",
                formData,
                {
                    headers: self.$headers
                }
            )

            if (response.data.status == "success") {
            	// update the group status in local array
            	const user = response.data.user

            	const groups = store.getters.getGroups
            	for (let a = 0; a < groups.length; a++) {
            		if (groups[a]._id == _id) {
            			for (let b = 0; b < groups[a].members.length; b++) {
            				if (groups[a].members[b].user._id == user._id) {
            					groups[a].members[b].status = "accepted"
            					break
            				}
            			}
            			break
            		}
            	}
            	store.commit("setGroups", groups)

            	swal.fire("Group Invitation", response.data.message, "success")
            } else {
                swal.fire("Error", response.data.message, "error")
            }

		}
	})
},

It will ask for confirmation first. After the user confirms it, then it will call an AJAX to the server to update it in Mongo DB. After the response is received from the server, we will check if the response status is “success”. If yes, then it will update the group’s status in the local array too.

Now we need to create an API that will handle this request. So open your api/modules/groups.js and write the following API in it:

router.post("/acceptInvite", auth, async function (request, result) {
    // get logged-in users
    const user = request.user;

    // get unique ID of group
    const _id = request.fields._id;

    // check if group exists
    const group = await db.collection("groups").findOne({
        "_id": ObjectId(_id)
    });

    if (group == null) {
        result.json({
            status: "error",
            message: "Group does not exists."
        });
        return;
    }

    // set status to accepted in member's array
    await db.collection("groups").findOneAndUpdate({
        $and: [{
            _id: group._id
        }, {
            "members.user._id": user._id
        }]
    }, {
        $set: {
            "members.$.status": "accepted"
        }
    });

    // send the response back to client
    result.json({
        status: "success",
        message: "Invitation has been accepted.",
        user: user
    });
});

It will set the member’s status to accepted. If you test the app now and join any of the groups, you will notice that it will immediately turn to “Leave group”.

join group
join group

The user has now joined the group, now we need to give him the ability to leave the group anytime he wants.