Add ExclusiveContentcontainer with route.

This commit is contained in:
PascalMarchesseault
2024-09-20 14:31:18 -04:00
parent 8837dc5be1
commit b3fec80607
6 changed files with 269 additions and 3 deletions

View File

@@ -22,6 +22,8 @@ import Explorer from "@/views/explorer/explorer.vue";
import {useAuthStore} from "@/stores/authStore.js";
import ForYouPage from "@/views/profile/ForYouPage.vue";
import CreatorPresentation from "@/views/creators/CreatorPresentation.vue";
import CreatorExclusiveContent from "@/views/creators/CreatorExclusiveContent.vue";
const routes = [
{
@@ -50,6 +52,10 @@ const routes = [
path: '/content/post',
component: PostContent,
},
{
path: '/@:creator/exclusivecontent',
component: CreatorExclusiveContent
},
{
path: '/helpandcontact',

View File

@@ -0,0 +1,80 @@
<template>
<div :style="{ backgroundColor: '#2D2728' }">
<div class="mt-10" v-if="creator && creator.id">
<div class="max-w-[1500px] mx-auto">
<creator-banner :creator="creator"
@content-posted="contentPosted"
></creator-banner>
</div>
</div>
<div v-else>
<div v-if="loading">
<v-progress-linear indeterminate></v-progress-linear>
</div>
<div v-else>
<v-card>
<v-card-text style="text-align: center;">
Aucun créateur au nom de {{ route.params.creator }}
</v-card-text>
</v-card>
</div>
</div>
<div class="flex flex-row max-w-[1500px] mx-auto justify-center mt-8">
<div>
<div class="flex flex-column px-2 max-w-[1200px]">
<exclusive-content-container :creator="creator"></exclusive-content-container>
</div>
</div>
<div class="max-w-80 hidden xl:block">
<!-- Rewards component will be visible only on xl screens -->
<rewards :creator="creator"></rewards>
</div>
</div>
</div>
</template>
<script async setup>
import {watch, ref, onBeforeMount} from 'vue';
import {useRoute} from 'vue-router';
import {useClient} from "@/plugins/api.js";
import CreatorBanner from "@/views/creators/CreatorBanner.vue";
import Creatornewssummary from "@/views/creators/CreatorNewsSummary.vue";
import Rewards from "@/views/creators/Rewards.vue";
import ExclusiveContentContainer from "@/views/creators/ExclusiveContentContainer.vue";
const creator = ref(null)
const loading = ref(true)
const contents = ref([])
const client = useClient()
const route = useRoute()
function contentPosted(content) {
contents.value.unshift(content)
}
onBeforeMount(async () => await fetchCreatorData(route.params.creator))
watch(
() => route.params.creator,
async () => await fetchCreatorData(route.params.creator)
)
const fetchCreatorData = async (creatorAlias) => {
try {
loading.value = true
const response = await client.get(`/api/creators/@${creatorAlias}`)
creator.value = response.data
} catch (error) {
console.error(`Error fetching content: ${error}`)
} finally {
loading.value = false
}
}
</script>

View File

@@ -42,8 +42,8 @@ import {watch, ref, onBeforeMount} from 'vue';
import {useRoute} from 'vue-router';
import {useClient} from "@/plugins/api.js";
import CreatorBanner from "@/views/creators/CreatorBanner.vue";
import Creatornewssummary from "@/views/creators/banner/Creatornewssummary.vue";
import Rewards from "@/views/creators/banner/Rewards.vue";
import Creatornewssummary from "@/views/creators/CreatorNewsSummary.vue";
import Rewards from "@/views/creators/Rewards.vue";
const creator = ref(null)

View File

@@ -0,0 +1,180 @@
<template>
<div class="overflow-hidden relative" @wheel="handleScroll">
<!-- Container that holds all the posts and permet le défilement -->
<div class="relative h-[1000px] max-h-[1000px] overflow-hidden p-4">
<div class="transition-transform duration-500" :style="{ transform: `translateY(-${scrollPosition}px)` }">
<!-- Grille avec colonnes dynamiques basées sur la largeur -->
<div class="grid gap-3 grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 min-w-[250px]">
<div v-for="(item, index) in contenuexclusif" :key="index"
class="my-1 text-white rounded-lg w-full border-2 shadow h-[380px] hover-card relative overflow-hidden"
:style="{
background: creator.colors.bannerTop,
borderColor: `rgba(${getRGB(creator.colors.bannerBottom)}, 0.38)`
}">
<div class="flex justify-center items-center">
</div>
<div>
<img :src="item.photo" class="w-full h-auto max-h-[170px] object-cover" />
<!-- Section du nombre de clics et du bouton d'édition -->
<div class="flex flex-row justify-between items-center p-2">
<div class="flex items-center">
<p class="text-xs">{{ item.date }}</p>
<p class="text-xs px-2">|</p>
<p class="text-xs">200 clicks</p>
</div>
<!-- Bouton pour éditer le contenu à droite -->
<v-btn class="" icon variant="plain" @click="editCard(item)">
<v-icon>mdi-dots-vertical</v-icon>
</v-btn>
</div>
<p class="text-md p-4">{{ item.title }}</p>
<!-- Section des étoiles, fixée dans le coin inférieur droit -->
<div v-if="item.rating" class="stars flex justify-end p-2 absolute bottom-0 right-0">
<!-- Génération dynamique des étoiles -->
<span v-for="star in 5" :key="star" class="text-yellow-500">
<v-icon v-if="star <= item.rating">mdi-star</v-icon>
<v-icon v-else>mdi-star-outline</v-icon>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed, defineProps } from 'vue';
function hexToRgb(hex) {
let shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
hex = hex.replace(shorthandRegex, function(m, r, g, b) {
return r + r + g + g + b + b;
});
let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
function getRGB(hexColor) {
const rgb = hexToRgb(hexColor);
return `${rgb.r}, ${rgb.g}, ${rgb.b}`;
}
const contenuexclusif = ref([
{ title: 'Créer un site web moderne', description: 'Un guide pour concevoir un site qui attire l\'attention et se démarque.', photo: '/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile01.png', rating: 2, date: '2024-09-19' },
{ title: ' Les secrets dun logo réussiLes secrets dun logo réussiLes secrets dun logo réussi', description: 'Découvrez les astuces pour un logo mémorable et distinctif.Découvrez les astuces pour un logo mémorable et distinctif.', photo: '/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile01.png', rating: 4, date: '2024-09-19' },
{ title: 'Les secrets dun logo réussi', description: 'Découvrez les astuces pour un logo mémorable et distinctif.', photo: '/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile01.png', rating: 4, date: '2024-09-19' },
{ title: 'Les secrets dun logo réussi', description: 'Découvrez les astuces pour un logo mémorable et distinctif.', photo: '/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile01.png', rating: 4, date: '2024-09-19' },
{ title: 'Les secrets dun logo réussi', description: 'Découvrez les astuces pour un logo mémorable et distinctif.', photo: '/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile01.png', rating: 4, date: '2024-09-19' },
{ title: 'Les secrets dun logo réussi', description: 'Découvrez les astuces pour un logo mémorable et distinctif.', photo: '/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile01.png', rating: 4, date: '2024-09-19' },
{ title: 'Les secrets dun logo réussi', description: 'Découvrez les astuces pour un logo mémorable et distinctif.', photo: '/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile01.png', rating: 4, date: '2024-09-19' },
{ title: 'Les secrets dun logo réussi', description: 'Découvrez les astuces pour un logo mémorable et distinctif.', photo: '/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile01.png', rating: 4, date: '2024-09-19' },
{ title: 'Les secrets dun logo réussi', description: 'Découvrez les astuces pour un logo mémorable et distinctif.', photo: '/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile01.png', rating: 4, date: '2024-09-19' },
{ title: 'Les secrets dun logo réussi', description: 'Découvrez les astuces pour un logo mémorable et distinctif.', photo: '/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile01.png', rating: 4, date: '2024-09-19' },
{ title: 'Les secrets dun logo réussi', description: 'Découvrez les astuces pour un logo mémorable et distinctif.', photo: '/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile01.png', rating: 4, date: '2024-09-19' },
{ title: 'Les secrets dun logo réussi', description: 'Découvrez les astuces pour un logo mémorable et distinctif.', photo: '/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile01.png', rating: 4, date: '2024-09-19' },
{ title: 'Les secrets dun logo réussi', description: 'Découvrez les astuces pour un logo mémorable et distinctif.', photo: '/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile01.png', rating: 4, date: '2024-09-19' },
{ title: 'Les secrets dun logo réussi', description: 'Découvrez les astuces pour un logo mémorable et distinctif.', photo: '/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile01.png', rating: 4, date: '2024-09-19' },
{ title: 'Les secrets dun logo réussi', description: 'Découvrez les astuces pour un logo mémorable et distinctif.', photo: '/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile01.png', rating: 4, date: '2024-09-19' },
{ title: 'Les secrets dun logo réussi', description: 'Découvrez les astuces pour un logo mémorable et distinctif.', photo: '/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile01.png', rating: 4, date: '2024-09-19' },
// autres objets...
]);
const scrollPosition = ref(0);
const cardHeight = 320;
const props = defineProps({
creator: {
type: Object,
required: true,
},
});
function handleScroll(event) {
event.preventDefault();
const scrollSpeed = 100;
scrollPosition.value += event.deltaY > 0 ? scrollSpeed : -scrollSpeed;
const totalRows = Math.ceil(contenuexclusif.value.length / getCurrentCols());
const visibleRows = 1000 / cardHeight;
const maxScrollPosition = totalRows * cardHeight - visibleRows * cardHeight + 360;
if (scrollPosition.value < 0) {
scrollPosition.value = 0;
} else if (scrollPosition.value > maxScrollPosition) {
scrollPosition.value = maxScrollPosition;
}
}
const gridColsClass = computed(() => {
const width = window.innerWidth;
if (width >= 1200) {
return 'grid-cols-4';
} else if (width >= 900) {
return 'grid-cols-3';
} else if (width >= 600) {
return 'grid-cols-2';
} else {
return 'grid-cols-1';
}
});
function getCurrentCols() {
const width = window.innerWidth;
if (width >= 1200) {
return 4;
} else if (width >= 900) {
return 3;
} else if (width >= 600) {
return 2;
} else {
return 1;
}
}
function editCard(item) {
console.log(`Editing card: ${item.title}`);
}
window.addEventListener('resize', () => {
gridColsClass.value = getCurrentCols();
});
</script>
<style>
.hover-card {
transition: transform 0.3s ease-in-out;
}
.hover-card:hover {
transform: scale(1.03); /* Effet de hover restauré */
}
.stars .v-icon {
font-size: 18px; /* Ajustez la taille des icônes */
}
.limited-text {
height: 60px; /* Limite la hauteur du texte */
overflow: hidden; /* Empêche le texte de dépasser */
text-overflow: ellipsis; /* Ajoute des points de suspension si le texte dépasse */
white-space: nowrap; /* Le texte reste sur une seule ligne */
}
.stars {
position: absolute; /* Fixe les étoiles au bas à droite */
bottom: 10px;
right: 10px;
}
</style>