How can I make my cards into a deck of cards?

Hi guys,

I would like to create a deck of flashcards. You flip the card, flip it back, move the card at the back of the deck, and you see the next card. I have an array of cards and I would like to display a deck of cards so one card behind the other. When a person clicks a button the next card is displayed. This is what I currently have where all cards are displayed in a column. I haven’t written the logic of changing to the next card yet, right now I’m just trying to get all the cards to be behind one another. Is this a good way of approaching this problem or would suggest another way of creating a deck of cards? I’m also open to suggestions. I’m also using Vue Composition API and Tailwind

<template>
    <AuthenticatedLayout>
        <template #header>
            <h2 class="font-semibold text-xl text-gray-800 leading-tight">
                {{ deck.title }}
            </h2>
        </template>
        <div class="relative">
            <div
                v-for="(card, index) in deck.cards"
                :key="card.id"
                class="margin-right font-semibold mt-6 flex flex-row flex-wrap justify-center items-center transition-transform duration-500 ease-in-out"
            >
                <div
                    class="mx-3 w-[700px] h-[450px] dark:text-slate-200 bg-white border border-gray-200 rounded-lg shadow dark:bg-sky-950 dark:border-sky-950 mb-2 w-80 h-80 flex flex-col justify-between cursor-pointer group perspective flex flex-row justify-between relative preserve-3d duration-1000"
                    :class="{ 'flip-card': flippedStates[index] }"
                    @click="toggleFlip(index)"
                >
                    <div class="backface-hidden w-full h-full p-4">
                        <p>{{ card.hint }}</p>
                        <h3
                            class="text-center flex flex-col items-center justify-center h-full px-2 pb-24 text-3xl font-semibold text-center"
                        >
                            {{ card.question }}
                        </h3>
                    </div>

                    <p>{{ deck.question }}</p>
                    <div
                        class="absolute flip-card backface-hidden w-full h-full dark:bg-sky-950 dark:border-sky-950 rounded-lg"
                    >
                        <div
                            class="text-center flex flex-col items-center justify-center h-full px-2 pb-24"
                        >
                            <p>
                                {{ card.answer }}
                            </p>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <button
            @click="showNextCard"
            class="mt-4 px-4 py-2 bg-blue-500 text-white rounded-lg"
        >
            Next Card
        </button>
    </AuthenticatedLayout>
</template>

Hello!

I don’t know much about Vue, but I know how I would approach this with React and I think you can translate this design into Vue components.

You’ll need three components that will be working together:

A parent component that has two arrays with all suits and card values and that displays the Deck component.

A " Deck" component that maps through the arrays above and stacks the Card components on top of each other with CSS. The “Deck” component uses the Card component.

A “Card” component that gets its values from the two components above. Will be reused for all 52 cards. You can then write the logic what the user can do with a single Card component like flipping or dragging it.

Ok, so here is what I currently have. Right now all my cards are one behind the other just like in a deck of cards. When I click a card it flips to show the back of the card. I click it again and it shows the front of the card but as the card is flipping you can see the next card behind it. How can I make the cards behind the card I’m currently viewing invisible/hidden? Again, is this a good way of going about this? Would there be a better way? Again, im open to suggestions.

<script setup>
import { ref } from "vue";
import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout.vue";
const { deck } = defineProps(["deck"]);

// Create an array to store the flipped state for each card
const newDeck = deck.cards.reverse();

const flippedStates = ref(new Array(newDeck.length).fill(false));

const toggleFlip = (index) => {
    // Update the flipped state of the clicked card
    flippedStates.value[index] = !flippedStates.value[index];
};
</script>

<template>
    <AuthenticatedLayout>
        <template #header>
            <h2 class="font-semibold text-xl text-gray-800 leading-tight">
                {{ deck.title }}
            </h2>
        </template>
        <div class="flex flex-col">
            <div
                v-for="(card, index) in deck.cards"
                :key="card.id"
                class="m-5 font-semibold absolute inset-x-0 flex flex-wrap justify-center items-center transition-transform duration-500 ease-in-out"
            >
                <div
                    class="w-[700px] h-[450px] dark:text-slate-200 bg-white border border-gray-200 rounded-lg shadow dark:bg-sky-950 dark:border-sky-950 mb-2 w-80 h-80 flex flex-col justify-between cursor-pointer group perspective relative preserve-3d duration-1000"
                    :class="{
                        'flip-card': flippedStates[index],
                    }"
                    @click="toggleFlip(index)"
                >
                    <div class="backface-hidden w-full h-full p-4">
                        <p>{{ card.hint }}</p>
                        <h3
                            class="text-center flex flex-col items-center justify-center h-full px-2 pb-24 text-3xl font-semibold text-center"
                        >
                            {{ card.question }}
                        </h3>
                    </div>

                    <p>{{ deck.question }}</p>
                    <div
                        class="absolute flip-card backface-hidden w-full h-full dark:bg-sky-950 dark:border-sky-950 rounded-lg"
                    >
                        <div
                            class="text-center flex flex-col items-center justify-center h-full px-2 pb-24"
                        >
                            <p>
                                {{ card.answer }}
                            </p>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </AuthenticatedLayout>
</template>