Scyne
Scyne

Reputation: 33

Am I not properly performing update(goal)?

I am building an app in Vue that is tracking the sum of donations paid to my ExtraLife Team and tallies them up based on a user-submitted #tag in the message provided with the donation. Currently, I've been working on a Goal Editor view using what I've named the adminView component to display the full goals table and allow a user to edit the rows. The problem that I'm having is that for some reason when I attempt to update(goal) I'm getting a 400 (Bad Request) response. Obviously, I must have something malformed or missing in the data, I'm just not seeing what.

Here is my current @/components/AdminView.vue (Auth url and Key Removed)

<template>
  <div id="adminView">
    <h1>Goal Editor</h1>
    <table style="border-collapse: collapse; width: 80%">
      <thead>
        <tr style="border: 1px solid #ddd">
          <th
            style="
              padding: 8px;
              text-align: left;
              border: 1px solid #ddd;
              width: 3%;
            "
          >
            ID
          </th>
          <th
            style="
              padding: 8px;
              text-align: left;
              border: 1px solid #ddd;
              width: 5%;
            "
          >
            Tag
          </th>
          <th
            style="
              padding: 8px;
              text-align: left;
              border: 1px solid #ddd;
              width: 35%;
            "
          >
            Description
          </th>
          <th
            style="
              padding: 8px;
              text-align: left;
              border: 1px solid #ddd;
              width: 10%;
            "
          >
            Target Amount
          </th>
          <th
            style="
              padding: 8px;
              text-align: left;
              border: 1px solid #ddd;
              width: 10%;
            "
          >
            Current Donations
          </th>
          <th
            style="
              padding: 8px;
              text-align: left;
              border: 1px solid #ddd;
              width: 4%;
            "
          >
            Active
          </th>
          <th
            style="
              padding: 8px;
              text-align: left;
              border: 1px solid #ddd;
              width: 6%;
            "
          ></th>
        </tr>
      </thead>
      <tbody>
        <tr
          v-for="(goal, index) in goals"
          :key="goal.goal_id"
          :style="[index % 2 == 0 ? 'background-color: #f2f2f2' : '']"
        >
          <td style="padding: 8px; text-align: left; border: 1px solid #ddd">
            {{ goal.goal_id }}
          </td>
          <td style="padding: 8px; text-align: left; border: 1px solid #ddd">
            <input
              v-model="goal.tag"
              v-if="goal.editing"
              type="text"
              style="border: none; outline: none; width: 100%"
            />
            <span v-else>#{{ goal.tag }}</span>
          </td>
          <td style="padding: 8px; text-align: left; border: 1px solid #ddd">
            <input
              v-model="goal.goal_description"
              v-if="goal.editing"
              type="text"
              style="border: none; outline: none; width: 100%"
            />
            <span v-else>{{ goal.goal_description }}</span>
          </td>
          <td style="padding: 8px; text-align: left; border: 1px solid #ddd">
            <input
              v-model="goal.goal_target"
              v-if="goal.editing"
              type="number"
              style="border: none; outline: none; width: 100%"
            />
            <span v-else>${{ goal.goal_target }}</span>
          </td>
          <td style="padding: 8px; text-align: left; border: 1px solid #ddd">
            <input
              v-model="goal.goal_tally"
              v-if="goal.editing"
              type="number"
              style="border: none; outline: none; width: 100%"
            />
            <span v-else>${{ goal.goal_tally }}</span>
          </td>
          <td style="padding: 8px; text-align: left; border: 1px solid #ddd">
            <input
              v-model="goal.active"
              v-if="goal.editing"
              type="checkbox"
              style="outline: none"
            />
            <span v-else>{{ goal.active }}</span>
          </td>
          <td style="padding: 8px; text-align: center; border: 1px solid #ddd">
            <button
              v-if="goal.editing"
              @click="saveGoal(goal)"
              style="
                outline: none;
                border: none;
                background-color: #4caf50;
                color: white;
                padding: 8px 16px;
                text-align: center;
                text-decoration: none;
                display: inline-block;
                font-size: 16px;
                cursor: pointer;
              "
            >
              Save
            </button>
            <button
              v-else
              @click="editGoal(goal)"
              style="
                outline: none;
                border: none;
                background-color: #f2f2f2;
                color: black;
                padding: 8px 16px;
                text-align: center;
                text-decoration: none;
                display: inline-block;
                font-size: 16px;
                cursor: pointer;
              "
            >
              Edit
            </button>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
import { createClient } from "@supabase/supabase-js"; // Import the Supabase client

export default {
  name: "adminView",
  data() {
    return {
      supabase: null,
      session: null,
      error: null,
      goals: [],
    };
  },
  async created() {
    // Create the Supabase client object
    this.supabase = createClient(
      "MY DB URL IS HERE",
      "MY DB SECRET KEY IS HERE"
    );

    // Fetch the current user's session
    const { data, error } = await this.supabase.auth.getSession();
    this.session = data;
    this.error = error;

    // Fetch the goals from the database
    await this.fetchGoals();
  },
  methods: {
    async fetchGoals() {
      console.log("Fetching goals...");
      const { data, error } = await this.supabase.from("goals").select("*");
      console.log(data, error);
      this.goals = data;
      console.log("Goals fetched!");
      console.log(this.goals);
    },
    editGoal(goal) {
      goal.editing = true;
    },
    async saveGoal(goal) {
      console.log(goal);
      goal.editing = false;
      await this.supabase.from("goals").update(goal);
    },
  },
};
</script>

<style>
#adminView {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
</style>

Upvotes: 1

Views: 30

Answers (1)

Scyne
Scyne

Reputation: 33

Thanks to a comment from @kissu I remembered to check the network tab and compared it to a manual request and discovered that I had an extra value in this.goal that was making it's way into the request. I fixed by deleting the extra value and then setting it back to false.

async saveGoal(goal) {
      delete goal.editing;
      console.log(goal);
      await this.supabase
        .from("goals")
        .update(goal)
        .eq("goal_id", goal.goal_id);
      goal.editing = false;
    },

Upvotes: 1

Related Questions