Picture Competition Web App - Node JS, Mongo DB and Vue JS

Create a Picture Competition Website in Express JS, MEVN

0
(0)

Competition Detail Page

Now we need to create a page where we can display more details about a specific competition. For example, we can show a list of all voters on that page, all comments on competition, etc. First, go to your “competition-slider.ejs” and change line #44 from:

{{ competition.user1.name }} vs {{ competition.user2.name }}

To:

<a v-bind:href="baseUrl + '/competitionDetail/' + competition._id">
	{{ competition.user1.name }} vs {{ competition.user2.name }}
</a>

It will create a hyperlink to the competition detail route. It will also send the competition ID in the URL as a parameter. Now we need to create a GET route in “server.js” that will render the competition detail page:

app.route("/competitionDetail/:_id")
	.get(function (request, result) {
		const _id = request.params._id;
		result.render("competition-detail", {
			"_id": _id
		});
	});

It will get the competition ID from the URL and pass it on to the new page. Create a file named “competition-detail.ejs” inside your “views” folder. Following will be the code of this file:

<%- include ("includes/header") %>

<input type="hidden" id="_id" value="<%= _id %>" />

<div class="container margin-container" id="competitionDetailApp" style="margin-bottom: 50px;">
	<div class="row">
		<div class="col-md-12">
			<h1 class="text-center" v-if="competition != null">{{ competition.user1.name + " vs " + competition.user2.name }}</h1>
			<h1 class="text-center" v-if="competition == null">Loading...</h1>
		</div>
	</div>

	<div class="row" v-if="competition != null" style="margin-top: 40px; margin-bottom: 40px;">
        <div class="col-md-6">
            <table class="table table-bordered table-responsive">
                <tr>
                    <th class="text-center">
                        {{ competition.user1.name }}

                        ({{ competition.user1.voters.length }})
                    </th>
                </tr>

                <tr>
                    <td>
                        <img v-bind:src="baseUrl + '/' + competition.user1.picture" class="img-responsive" style="width: 100%;" />
                    </td>
                </tr>
            </table>
        </div>

        <div class="col-md-6">
            <table class="table table-bordered table-responsive">
                <tr>
                    <th class="text-center">
                        {{ competition.user2.name }}

                        ({{ competition.user2.voters.length }})
                    </th>
                </tr>

                <tr>
                    <td>
                        <img v-bind:src="baseUrl + '/' + competition.user2.picture" class="img-responsive" style="width: 100%;" />
                    </td>
                </tr>
            </table>
        </div>
    </div>

    <div class="row" v-if="competition != null">
    	<div class="col-md-12">
    		<p class="text-center" v-text="competition.tags"></p>
    	</div>
    </div>

    [all comments]

    [add a comment]
</div>

<script>
	var competitionDetailApp = new Vue({
		el: "#competitionDetailApp",
		data: {
			baseUrl: mainURL,
			id: document.getElementById("_id").value,
			competition: null
		},
		methods: {

			getCompetitionDetail: function () {
				var self = this;

				var formData = new FormData();
		        formData.append("accessToken", localStorage.getItem(accessTokenKey));
		        formData.append("_id", this.id);

				myApp.callAjax(this.baseUrl + "/competitionDetail/" + this._id, formData, function (response) {
                    // convert the JSON string into Javascript object
                    var response = JSON.parse(response);
                    // console.log(response);
 
                    // if the user is created, then redirect to login
                    if (response.status == "success") {
                    	self.competition = response.competition;
                    } else {
                    	swal("Error", response.message, "error");
                    }
				});
			}
		},
		mounted: function () {
			this.getCompetitionDetail();
		}
	});
</script>

<%- include ("includes/footer") %>

This will show both user’s names and pictures along with all the people who have voted for each user. This also shows the hashtags of competition (if there are any). This calls an AJAX to the server when the page loads. So we need to add a POST route too at our “/competitionDetail” route in “server.js”:

app.route("/competitionDetail/:_id")
	.get(function (request, result) {
		const _id = request.params._id;
		result.render("competition-detail", {
			"_id": _id
		});
	})
	.post(async function (request, result) {
		const accessToken = request.fields.accessToken;
		const _id = request.fields._id;

		var user = await db.collection("users").findOne({
	        "accessToken": accessToken
	    });
	    if (user == null) {
	        result.json({
	            "status": "error",
	            "message": "User has been logged out. Please login again."
	        });
	        return false;
	    }

	    var competition = await db.collection("competitions").findOne({
	        "_id": ObjectId(_id)
	    });
        // sort the comments in descending order,
        // so that the new comments appear at the top
        competition.comments = competition.comments.reverse();

	    result.json({
            "status": "success",
            "message": "Data has been fetched.",
            "competition": competition
        });
	});

This post route will first check if the user is logged in or not. Then it will fetch the competition data from Mongo DB. Refresh the page now and you will be able to see the competition details.

How useful was this post

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

As you found this post useful...

Follow us on social media!

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post





Leave a Reply