From 4781382d51cd6e64e82f0ade23338ff7cf649b43 Mon Sep 17 00:00:00 2001 From: Trenton Zimmer <66042448+trmazi@users.noreply.github.com> Date: Sun, 27 Oct 2024 23:03:51 -0400 Subject: [PATCH] Add card saving and deleting --- src/colors.js | 6 ++-- src/components/FooterBar.vue | 2 +- src/components/UserCard.vue | 4 +-- src/stores/api/account.js | 34 ++++++++++++++++++++ src/stores/main.js | 19 ++++++----- src/views/Profile/CardsView.vue | 57 ++++++++++++++++++++++++++++----- 6 files changed, 98 insertions(+), 24 deletions(-) diff --git a/src/colors.js b/src/colors.js index cdcd6db..24363fa 100644 --- a/src/colors.js +++ b/src/colors.js @@ -46,7 +46,7 @@ export const getButtonColor = ( lightDark: "ring-gray-200 dark:ring-gray-500", contrast: "ring-gray-300 dark:ring-gray-400", success: "ring-emerald-300 dark:ring-emerald-700", - danger: "ring-red-300 dark:ring-red-700", + danger: "ring-red-300 dark:ring-red-900", warning: "ring-yellow-300 dark:ring-yellow-700", info: "ring-blue-300 dark:ring-blue-800", }, @@ -89,8 +89,8 @@ export const getButtonColor = ( lightDark: "border-gray-100 dark:border-slate-800", contrast: "border-gray-800 dark:border-white", success: "border-emerald-600 dark:border-emerald-800", - danger: "border-red-600 dark:border-red-500", - warning: "border-yellow-600 dark:border-yellow-900", + danger: "border-red-600 dark:border-ruby-950", + warning: "border-yellow-600 dark:border-yellow-950", info: "border-blue-600 dark:border-blue-950", }, text: { diff --git a/src/components/FooterBar.vue b/src/components/FooterBar.vue index e1df8c2..de930d1 100644 --- a/src/components/FooterBar.vue +++ b/src/components/FooterBar.vue @@ -20,7 +20,7 @@ import BaseButton from "@/components/BaseButton.vue";

- {{ greeting.header[0] }} - {{ mainStore.userName }} {{ greeting.header[1] }} + {{ greeting.header[0] }}{{ mainStore.userName }} {{ greeting.header[1] }}

{{ mainStore.userName }} diff --git a/src/stores/api/account.js b/src/stores/api/account.js index 6b1e826..134b484 100644 --- a/src/stores/api/account.js +++ b/src/stores/api/account.js @@ -56,3 +56,37 @@ export async function APIUpdatePassword( throw error; } } + +export async function APIGetCards() { + try { + const data = await mainStore.callApi(`/user/card`); + return data.cards; + } catch (error) { + console.log("Error fetching cards:", error); + throw error; + } +} + +export async function APIPutCard(cardId) { + try { + const data = await mainStore.callApi(`/user/card`, "POST", { + cardId: cardId, + }); + return data; + } catch (error) { + console.log("Error adding card:", error); + throw error; + } +} + +export async function APIDeleteCard(cardId) { + try { + const data = await mainStore.callApi(`/user/card`, "DELETE", { + cardId: cardId, + }); + return data; + } catch (error) { + console.log("Error deleting card:", error); + throw error; + } +} diff --git a/src/stores/main.js b/src/stores/main.js index b3ee699..897c10a 100644 --- a/src/stores/main.js +++ b/src/stores/main.js @@ -75,6 +75,15 @@ export const useMainStore = defineStore("main", { }, async callApi(endpoint, method = "GET", data = null, extraHeaders = {}) { + if (method === "DELETE") { + const confirmed = window.confirm("Are you really?"); + if (!confirmed) { + this.isSaving = false; + this.isLoading = false; + return null; // Exit if user does not confirm + } + } + const apiServer = import.meta.env.VITE_API_URL; const apiKey = import.meta.env.VITE_API_KEY; let loadingTimeout; @@ -263,16 +272,6 @@ export const useMainStore = defineStore("main", { } }, - async getCards() { - try { - const data = await this.callApi(`/user/cards`); - return data.cards; - } catch (error) { - console.log("Error fetching cards:", error); - throw error; - } - }, - async getArcade(arcadeId) { try { const data = await this.callApi(`/arcade/${arcadeId}`); diff --git a/src/views/Profile/CardsView.vue b/src/views/Profile/CardsView.vue index 74fbaa7..e1dd20b 100644 --- a/src/views/Profile/CardsView.vue +++ b/src/views/Profile/CardsView.vue @@ -15,23 +15,58 @@ import FormControl from "@/components/FormControl.vue"; import LayoutAuthenticated from "@/layouts/LayoutAuthenticated.vue"; import SectionTitleLine from "@/components/SectionTitleLine.vue"; -import { useMainStore } from "@/stores/main"; -const mainStore = useMainStore(); +import { APIGetCards, APIPutCard, APIDeleteCard } from "@/stores/api/account"; var cardData = ref([]); +const cardLoading = ref(false); const cardForm = reactive({ newCard: null, }); -onMounted(async () => { +async function loadCards() { + cardData.value = null; try { - const data = await mainStore.getCards(); + const data = await APIGetCards(); cardData.value = data; } catch (error) { console.error("Failed to fetch card data:", error); } +} + +onMounted(async () => { + await loadCards(); }); +function cardInput(event) { + var input = event.target.value; + input = input.replace(/[^A-Za-z0-9]/g, ""); + + // Format the input to XXXX-XXXX-XXXX-XXXX + input = input + .toUpperCase() + .replace(/(.{4})/g, "$1-") + .replace(/-$/, ""); + + cardForm.newCard = input; +} + +async function submitCard() { + cardLoading.value = true; + const response = await APIPutCard(cardForm.newCard); + if (response.status == "success") { + cardForm.newCard = null; + cardLoading.value = false; + await loadCards(); + } +} + +async function deleteCard(cardId) { + const response = await APIDeleteCard(dashCode(cardId)); + if (response.status == "success") { + await loadCards(); + } +} + const copyToClipboard = (text) => { navigator.clipboard .writeText(text) @@ -54,7 +89,7 @@ const copyToClipboard = (text) => { title="Register Card" main /> - + { name="cardId" type="card" placeholder="XXXX-XXXX-XXXX-XXXX" - minlength="16" + minlength="19" maxlength="19" required + @input="cardInput" />