Create a Picture Competition Website in Express JS, MEVN

Delete Competition

Now the creator of competition must have the power to delete a competition. So we need to show a delete button with each competition that will be visible to the creator of that competition. For that, first, we need to create a function in our “modules/functions.js” that will tell if the user is the creator of that competition:

competitionsWithUserOwner: function (competitions, user) {
  competitions.forEach(function (competition) {
    competition.isOwner = (competition.createdBy._id.toString() == user._id.toString());
  });
  return competitions;
},

Then goto “server.js” the POST route “/getAllCompetitions” and after all competitions are fetched, add the following line:

competitions = functions.competitionsWithUserOwner(competitions, user);

After that, go to your “competition-slider.ejs” file and replace the following code in the [delete competition button goes here] section:

<div v-if="competition.isOwner">
  <form method="POST" v-bind:action="baseUrl + '/deleteCompetition'" style="display: contents;" v-on:submit.prevent="deleteCompetition">
    <input type="hidden" name="id" v-model="competition._id" required />
    <button type="submit" name="submit" class="btn-delete">
      <i class="fa fa-trash"></i>
    </button>
  </form>
</div>

This will call a Javascript function when the form is submitted. So we need to create a function in our “competitionApp” object in “footer.ejs”:

deleteCompetition: function() {
  var form = event.target;
  var self = this;

  swal({
      title: "Are you sure?",
      text: "This competition will be deleted",
      icon: "warning",
      buttons: true,
      dangerMode: true,
  })
  .then(function(isOkay) {
      if (isOkay) {
          // disable the submit button and show "Loading..." text
          form.submit.setAttribute("disabled", "disabled");
          form.submit.innerHTML = "<i class='fa fa-spinner fa-spin'></i>";

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

          myApp.callAjax(form.getAttribute("action"), formData, function (response) {
              // convert the JSON string into Javascript object
              var response = JSON.parse(response);
              // console.log(response);

              // enable the submit button
              form.submit.removeAttribute("disabled");
              form.submit.innerHTML = "<i class='fa fa-trash'></i>";

              // if the user is created, then redirect to login
              if (response.status == "success") {
                  self.onCompetitionDeleted(form.id.value);
              } else {
                  swal("Error", response.message, "error");
              }
          });
      }
  });
},

This will ask for confirmation using a Sweetalert library. This calls an AJAX to the server and if the competition is deleted successfully then we need to remove it from the local array too. So create another method in this object that will do this:

onCompetitionDeleted: function(_id) {
  var self = this;
  this.competitions.forEach(function (competition, index) {
    if (competition._id.toString() == _id.toString()) {
      self.competitions.splice(index, 1);
    }
  });
},

After that, we need to create a POST route in “server.js” that will handle the AJAX request.

app.post("/deleteCompetition", 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."
    });
  }

  var competition = await db.collection("competitions").findOne({
    $and: [{
      "_id": ObjectId(id)
    }, {
      "createdBy._id": user._id
    }]
  });
  if (competition == null) {
    result.json({
      "status": "error",
      "message": "Competition not found."
    });
    return false;
  }

  fileSystem.unlink("public/" + competition.user1.picture, function (error) {
    if (error) {
      console.error(error);
      return false;
    }

    fileSystem.unlink("public/" + competition.user2.picture, async function (error) {
      if (error) {
        console.error(error);
        return false;
      }

      await db.collection("competitions").deleteOne({
        "_id": ObjectId(id)
      });

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

This will first check if the user is logged in. Then it will check if the competition is created by a logged-in user. Then it will remove the first user’s uploaded picture and then the second user’s uploaded pictures from the “uploads” folder. Finally, it will delete the competition from the Mongo DB as well. And send the response back to the client (AJAX).