Swipe cards one by one
This commit is contained in:
parent
6a818e9da5
commit
f9d5f0d856
@ -1,30 +1,27 @@
|
|||||||
<template>
|
<template>
|
||||||
<motion.img
|
<motion.img
|
||||||
:src="props.card.image"
|
v-if="currentCard"
|
||||||
|
:src="currentCard?.image"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
class="h-[60cqh] max-h-[800px] w-[400px] origin-bottom rounded-lg object-cover hover:cursor-grab active:cursor-grabbing md:w-[600px]"
|
class="h-[60cqh] max-h-[800px] w-[400px] origin-bottom rounded-lg object-cover hover:cursor-grab active:cursor-grabbing md:w-[600px]"
|
||||||
:style="{
|
:style="{
|
||||||
zIndex: props.isFront ? 500 : props.z,
|
|
||||||
gridRow: 1,
|
gridRow: 1,
|
||||||
gridColumn: 1,
|
gridColumn: 1,
|
||||||
transition: '0.125s transform',
|
transition: '0.125s transform',
|
||||||
x,
|
x,
|
||||||
opacity,
|
opacity,
|
||||||
rotate,
|
rotate,
|
||||||
boxShadow: isFront
|
boxShadow:
|
||||||
? '0 20px 25px -5px rgb(0 0 0 / 0.5), 0 8px 10px -6px rgb(0 0 0 / 0.5)'
|
'0 20px 25px -5px rgb(0 0 0 / 0.5), 0 8px 10px -6px rgb(0 0 0 / 0.5)',
|
||||||
: undefined,
|
|
||||||
}"
|
}"
|
||||||
alt="Picture of the author"
|
:alt="currentCard?.name"
|
||||||
:drag="dragValue"
|
drag="x"
|
||||||
:drag-constraints="{ left: 0, right: 0 }"
|
:drag-constraints="{ left: 0, right: 0 }"
|
||||||
:on-drag-end="handleDragEnd"
|
:on-drag-end="handleDragEnd"
|
||||||
:animate="{
|
|
||||||
scale: props.isFront ? 1 : 0.98,
|
|
||||||
}"
|
|
||||||
/>
|
/>
|
||||||
|
<h1 class="h-2 text-5xl">{{ currentCard?.name }}</h1>
|
||||||
|
|
||||||
<div v-if="props.isFront" class="flex justify-between">
|
<div v-if="currentCard" class="flex justify-between">
|
||||||
<!-- Pass Button -->
|
<!-- Pass Button -->
|
||||||
<button
|
<button
|
||||||
class="mx-12 flex h-24 w-42 flex-col items-center justify-center rounded-xl bg-violet-500 text-4xl text-white shadow-lg transition-colors duration-150 hover:bg-violet-600 focus:ring-4 focus:ring-violet-300 focus:outline-none"
|
class="mx-12 flex h-24 w-42 flex-col items-center justify-center rounded-xl bg-violet-500 text-4xl text-white shadow-lg transition-colors duration-150 hover:bg-violet-600 focus:ring-4 focus:ring-violet-300 focus:outline-none"
|
||||||
@ -57,39 +54,48 @@ import type { Card } from "~/types/Card";
|
|||||||
const cardStore = useCardStore();
|
const cardStore = useCardStore();
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
card: {
|
cards: {
|
||||||
type: Object as PropType<Card>,
|
type: Object as PropType<Card[]>,
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
isFront: {
|
|
||||||
type: Boolean,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
z: {
|
|
||||||
type: Number,
|
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const dragValue = computed(() => (props.isFront ? "x" : false));
|
const emit = defineEmits<{
|
||||||
|
(e: "empty-list", isEmpty: boolean): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const currentCard = computed(() => props.cards[0]);
|
||||||
|
|
||||||
const x = useMotionValue(0);
|
const x = useMotionValue(0);
|
||||||
const opacity = useTransform(x, [-150, 0, 150], [0, 1, 0]);
|
const opacity = useTransform(x, [-150, 0, 150], [0, 1, 0]);
|
||||||
const rotate = useTransform(x, [-150, 150], [-18, 18]);
|
const rotate = useTransform(x, [-150, 150], [-18, 18]);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.cards.length,
|
||||||
|
(newLength, oldLength) => {
|
||||||
|
if (oldLength && oldLength > 0 && newLength === 0) {
|
||||||
|
emit("empty-list", true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
);
|
||||||
|
|
||||||
const handleDragEnd = () => {
|
const handleDragEnd = () => {
|
||||||
if (Math.abs(x.get()) > 50) {
|
if (Math.abs(x.get()) > 50) {
|
||||||
cardStore.removeCard(props.card.id);
|
cardStore.removeCard(currentCard?.value.id);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
async function swipeRight() {
|
async function swipeRight() {
|
||||||
console.log(props.card.id);
|
await animate(x, 150, { duration: 0.3 });
|
||||||
await animate(x, 300, { duration: 0.3 });
|
cardStore.smashList.push(currentCard.value);
|
||||||
cardStore.removeCard(props.card.id);
|
cardStore.removeCard(currentCard.value.id);
|
||||||
|
await animate(x, 0, { duration: 0.6 });
|
||||||
}
|
}
|
||||||
async function swipeLeft() {
|
async function swipeLeft() {
|
||||||
await animate(x, -300, { duration: 0.3 });
|
await animate(x, -150, { duration: 0.3 });
|
||||||
cardStore.removeCard(props.card.id);
|
cardStore.passList.push(currentCard.value);
|
||||||
|
cardStore.removeCard(currentCard.value.id);
|
||||||
|
await animate(x, 0, { duration: 0.6 });
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -18,6 +18,7 @@ export default defineNuxtConfig({
|
|||||||
runtimeConfig: {
|
runtimeConfig: {
|
||||||
public: {
|
public: {
|
||||||
apiBase: process.env.API_BASE_URL || "http://localhost:8000",
|
apiBase: process.env.API_BASE_URL || "http://localhost:8000",
|
||||||
|
isUploadActive: process.env.IS_UPLOAD_ACTIVE || "false",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
primevue: {
|
primevue: {
|
||||||
|
|||||||
@ -1,12 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="grid min-h-screen place-items-center">
|
<div v-if="loading">Loading...</div>
|
||||||
<CardView
|
<div v-else class="grid min-h-screen place-items-center">
|
||||||
v-for="(card, index) in cardStore.cards"
|
<CardView :cards="cardStore.cards" @empty-list="showResults" />
|
||||||
:key="card.id"
|
|
||||||
:card="card"
|
|
||||||
:is-front="index === 0"
|
|
||||||
:z="index"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -17,6 +12,14 @@ import { useCardStore } from "~/store/Card";
|
|||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const collection: string = route.query.collection as string;
|
const collection: string = route.query.collection as string;
|
||||||
const cardStore = useCardStore();
|
const cardStore = useCardStore();
|
||||||
|
const loading = ref(true);
|
||||||
|
|
||||||
cardStore.fetchCardsByCollection(collection);
|
onMounted(async () => {
|
||||||
|
cardStore.fetchCardsByCollection(collection);
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
const showResults = () => {
|
||||||
|
navigateTo("result");
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -26,68 +26,22 @@
|
|||||||
/>
|
/>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<UploadView />
|
<UploadView v-if="isUploadActive" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useCardStore } from "~/store/Card";
|
import { useCardStore } from "~/store/Card";
|
||||||
|
|
||||||
|
const config = useRuntimeConfig();
|
||||||
const cardStore = useCardStore();
|
const cardStore = useCardStore();
|
||||||
|
|
||||||
cardStore.fetchCollections();
|
cardStore.fetchCollections();
|
||||||
/*
|
|
||||||
cardStore.cards = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: "Pipi",
|
|
||||||
url: "https://images.unsplash.com/photo-1542291026-7eec264c27ff?q=80&w=2370&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: "Pipi",
|
|
||||||
url: "https://images.unsplash.com/photo-1512374382149-233c42b6a83b?q=80&w=2235&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
name: "Pipi",
|
|
||||||
url: "https://images.unsplash.com/photo-1539185441755-769473a23570?q=80&w=2342&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
name: "Pipi",
|
|
||||||
url: "https://images.unsplash.com/photo-1549298916-b41d501d3772?q=80&w=2224&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
name: "Pipi",
|
|
||||||
url: "https://images.unsplash.com/photo-1516478177764-9fe5bd7e9717?q=80&w=2340&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
id: 6,
|
|
||||||
name: "Pipi",
|
|
||||||
url: "https://images.unsplash.com/photo-1570464197285-9949814674a7?q=80&w=2273&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
id: 7,
|
|
||||||
name: "Pipi",
|
|
||||||
url: "https://images.unsplash.com/photo-1578608712688-36b5be8823dc?q=80&w=2187&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
id: 8,
|
|
||||||
name: "Pipi",
|
|
||||||
url: "https://images.unsplash.com/photo-1505784045224-1247b2b29cf3?q=80&w=2340&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
|
||||||
},
|
|
||||||
]; */
|
|
||||||
|
|
||||||
const activeItem = ref();
|
const activeItem = ref();
|
||||||
|
const isUploadActive = computed(() =>
|
||||||
|
config.public.isUploadActive === "true" ? true : false,
|
||||||
|
);
|
||||||
|
|
||||||
const play = (collection: string) => {
|
const play = (collection: string) => {
|
||||||
navigateTo({ path: "game", query: { collection: collection } });
|
navigateTo({ path: "game", query: { collection: collection } });
|
||||||
|
|||||||
@ -8,14 +8,14 @@
|
|||||||
class="grid grid-cols-1 gap-2 lg:grid-cols-3 xl:grid-cols-5 xl:gap-4"
|
class="grid grid-cols-1 gap-2 lg:grid-cols-3 xl:grid-cols-5 xl:gap-4"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-for="(img, idx) in imagesListOne"
|
v-for="card in cardStore.smashList"
|
||||||
:key="idx"
|
:key="card.id"
|
||||||
class="flex items-center justify-center rounded p-2 shadow"
|
class="flex items-center justify-center rounded p-2 shadow"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
:src="img"
|
:src="card.image"
|
||||||
alt="Image from Smash List"
|
alt="Image from Smash List"
|
||||||
class="h-32 w-full rounded object-cover"
|
class="w-full rounded object-cover"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -27,42 +27,29 @@
|
|||||||
class="grid grid-cols-1 gap-2 lg:grid-cols-3 xl:grid-cols-5 xl:gap-4"
|
class="grid grid-cols-1 gap-2 lg:grid-cols-3 xl:grid-cols-5 xl:gap-4"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-for="(img, idx) in imagesListTwo"
|
v-for="card in cardStore.passList"
|
||||||
:key="idx"
|
:key="card.id"
|
||||||
class="flex items-center justify-center rounded p-2 shadow"
|
class="flex items-center justify-center rounded p-2 shadow"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
:src="img"
|
:src="card.image"
|
||||||
alt="Image from pass list"
|
alt="Image from pass list"
|
||||||
class="h-32 w-full rounded object-cover"
|
class="w-full rounded object-cover"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Button label="Return" class="h-16 w-64" />
|
<Button label="Return" class="h-16 w-64" @click="goHome" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
const imagesListOne = [
|
import { useCardStore } from "~/store/Card";
|
||||||
// Replace with your image URLs
|
|
||||||
"https://picsum.photos/id/1011/200/200",
|
|
||||||
"https://picsum.photos/id/1012/800/400",
|
|
||||||
"https://picsum.photos/id/1013/200/200",
|
|
||||||
"https://picsum.photos/id/1014/200/200",
|
|
||||||
"https://picsum.photos/id/1015/200/200",
|
|
||||||
"https://picsum.photos/id/1016/200/200",
|
|
||||||
// ...more images
|
|
||||||
];
|
|
||||||
|
|
||||||
const imagesListTwo = [
|
const cardStore = useCardStore();
|
||||||
"https://picsum.photos/id/1021/200/200",
|
|
||||||
"https://picsum.photos/id/1022/200/200",
|
const goHome = () => {
|
||||||
"https://picsum.photos/id/1023/200/200",
|
navigateTo("");
|
||||||
"https://picsum.photos/id/1024/200/200",
|
};
|
||||||
"https://picsum.photos/id/1025/200/200",
|
|
||||||
"https://picsum.photos/id/1026/200/200",
|
|
||||||
// ...more images
|
|
||||||
];
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -29,7 +29,6 @@ export const useCardStore = defineStore("cardStore", {
|
|||||||
...card,
|
...card,
|
||||||
id: index,
|
id: index,
|
||||||
})) ?? [];
|
})) ?? [];
|
||||||
console.log(this.cards);
|
|
||||||
},
|
},
|
||||||
removeCard(id: number) {
|
removeCard(id: number) {
|
||||||
const index = this.cards.findIndex((card) => card.id === id);
|
const index = this.cards.findIndex((card) => card.id === id);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user