designtopack/src/components/inspirations/Image.vue

136 lines
3.3 KiB
Vue
Raw Normal View History

2024-09-11 07:32:34 +02:00
<template>
2024-11-19 13:59:06 +01:00
<figure class="flex">
<!-- Favorite button -->
2024-09-11 07:32:34 +02:00
<button
class="favorite"
2024-11-19 13:59:06 +01:00
:aria-label="isFavorite ? 'Retirer des favoris' : 'Ajouter aux favoris'"
2024-09-11 07:32:34 +02:00
:aria-pressed="isFavorite"
2024-11-19 13:59:06 +01:00
@click="toggleFavorite"
2024-09-11 07:32:34 +02:00
>
<svg
width="40"
height="40"
viewBox="0 0 40 40"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M5.49289 22.5821C5.50453 22.5937 5.51646 22.6051 5.52866 22.6161L19.3287 35.1161C19.7097 35.4613 20.2903 35.4613 20.6713 35.1161L34.4713 22.6161C34.4835 22.6051 34.4955 22.5937 34.5071 22.5821C38.7044 18.3848 37.6545 12.2706 34.2529 8.87931C32.5281 7.15976 30.1519 6.07621 27.4679 6.26656C25.0319 6.43932 22.4673 7.65151 20 10.1579C17.5321 7.65095 14.9651 6.43633 12.5266 6.25964C9.83985 6.06497 7.45863 7.14246 5.72977 8.85914C2.3178 12.247 1.27257 18.3618 5.49289 22.5821Z"
fill="currentColor"
stroke="white"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</button>
2024-11-19 13:59:06 +01:00
<!-- Image -->
2024-09-11 07:32:34 +02:00
<img :src="item.url" :alt="item.alt" :data-id="item.id" />
</figure>
</template>
2024-11-19 13:59:06 +01:00
2024-09-11 07:32:34 +02:00
<script setup>
2024-11-19 13:59:06 +01:00
// Imports
import { computed } from "vue";
2024-09-11 07:32:34 +02:00
import { useUserStore } from "../../stores/user";
import { useApiStore } from "../../stores/api";
2024-11-19 13:59:06 +01:00
// Props
2024-09-11 07:32:34 +02:00
const { item, inspirationUri } = defineProps({
item: Object,
inspirationUri: String,
});
2024-11-19 13:59:06 +01:00
// Stores
2024-09-11 07:32:34 +02:00
const { user } = useUserStore();
2024-11-19 13:59:06 +01:00
const api = useApiStore();
// State
const isFavorite = computed(() => {
return item.favoriteForUsers?.includes(user.uuid) ?? false;
2024-09-11 07:32:34 +02:00
});
2024-11-19 13:59:06 +01:00
// Methods
async function toggleFavorite() {
const previousState = isFavorite.value;
isFavorite.value = !isFavorite.value;
try {
const data = {
fileName: item.name,
userUuid: user.uuid,
inspirationUri,
};
const newFavoriteUsers = await api.fetchRoute(
"/toggle-favorite.json",
"POST",
data
);
// Update item favorite users list based on API response
item.favoriteForUsers = newFavoriteUsers;
} catch (error) {
console.error("Failed to toggle favorite:", error);
isFavorite.value = previousState; // Rollback on failure
}
}
2024-09-11 07:32:34 +02:00
</script>
2024-11-19 13:59:06 +01:00
2024-09-11 07:32:34 +02:00
<style scoped>
figure {
position: relative;
grid-row: span var(--rows);
width: 100%;
height: 100%;
border-radius: var(--rounded-2xl);
overflow: hidden;
}
img {
width: 100%;
height: 100%;
object-fit: cover;
}
figure:hover::after {
content: "";
position: absolute;
inset: 0;
background: var(--color-black-20);
z-index: 1;
}
figure:hover .favorite {
display: initial;
}
/* Favorite button */
.favorite {
position: absolute;
top: 0;
right: 0;
width: 3.5rem;
height: 3.5rem;
margin: var(--space-8);
padding: var(--space-8);
color: var(--color-grey-400);
display: none;
z-index: 10;
}
.favorite[aria-pressed="false"]:hover::before {
content: "Ajouter aux favoris";
2024-09-11 07:32:34 +02:00
background: var(--color-background);
padding: 1.3rem 3.5rem 1.25rem 1rem;
position: absolute;
z-index: -1;
inset: -2px;
left: unset;
width: max-content;
border-radius: var(--rounded-xl);
color: var(--color-grey-700);
letter-spacing: var(--tracking-wide);
font-weight: 500;
font-size: var(--text-sm);
}
.favorite[aria-pressed="true"] {
color: var(--color-brand);
}
</style>